P2765 魔术球问题
贪心模拟就可以过.........好像和dinic没啥关系
找找规律发现可以贪心放。n又灰常小。
设答案=m
你可以$O(mn)$直接模拟过去
闲的慌得话可以像我用个$set$维护
复杂度可以降为$O(mlogn)$
网络流.....不会写(逃
口胡一下dinic
一个点$u$拆成2个表示
1.放在柱子最下面,与S连接(u)
2.满足和下面的数的和为完全平方数,与T连接(u')
满足关系的两个点u、v,建立v-u'
当一个点被加入后,它就相当于放在最下面的点了。
去看luogu的题解吧(逃
#include<iostream> #include<cstdio> #include<set> using namespace std; struct data{ int val,id; bool operator < (const data &A) const{return val<A.val;} }; set<data> s; set<data>::iterator it; int n,w=1,tp[60][3000]; int main(){ scanf("%d",&n); s.insert((data){1,1}); for(int i=2;;++i){ while(i+(*s.begin()).val>w*w) ++w; it=s.upper_bound((data){w*w-i,0}); --it; if((*it).val+i!=w*w){ if(s.size()==n){printf("%d\n",i-1);break;} else{ int tmp=s.size()+1; s.insert((data){i,tmp}); } }else{ tp[(*it).id][++tp[(*it).id][0]]=(*it).val; s.insert((data){i,(*it).id}); s.erase(*it); } } for(it=s.begin();it!=s.end();++it) tp[(*it).id][++tp[(*it).id][0]]=(*it).val; for(int i=1;i<=n;++i){ for(int j=1;j<=tp[i][0];++j) printf("%d ",tp[i][j]); printf("\n"); }return 0; }