[網路流24題] 魔術球問題
阿新 • • 發佈:2018-12-09
Description
給定\(n(n\leq 55)\)個柱子,需要依次將編號為\(1,2,3...\)的球放上柱子,規定一個球能放上柱子當且僅當柱子為空或這個球的編號與柱子最上面球的編號的和為完全平方數。問最多能放幾個球。輸出方案。
Solution
先吐槽一句,網上用網路流寫的題解都tm太不詳細了,全是瞎jb寫,寫題解能不能有點責任心。氣tm死了,一上午都在看寫的不清楚的垃圾題解。 先說網上瞎jb講的題解,都是說對於每個球拆點,然後源點連一個,匯點連一個,中間不連。感覺網路流最重要的就是講清楚建圖的原因和代表的意義,然而網上根本沒有講為啥要這樣連,這裡講一下這樣連的意義是什麼。 我們先不要拿看待網路流的眼光看這題。我們把這\(m\)
Code
#include<cstdio> #include<cctype> #include<cstring> #include<iostream> #include<algorithm> #define N 5005 using std::min; using std::max; using std::swap; const int inf=0x3f3f3f3f; int d[N],s,t; int stk[N],top; int n,cnt,head[N]; struct Edge{ int to,nxt,flow; }edge[N*405]; void add(int x,int y,int z){ edge[++cnt].to=y; edge[cnt].nxt=head[x]; edge[cnt].flow=z; head[x]=cnt; } int getint(){ int x=0,f=0;char ch=getchar(); while(!isdigit(ch)) f|=ch=='-',ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return f?-x:x; } #include<queue> bool bfs(){ std::queue<int> q;q.push(s); memset(d,0,sizeof d);d[s]=1; while(q.size()){ int u=q.front();q.pop(); for(int i=head[u];i;i=edge[i].nxt){ int to=edge[i].to; if(!edge[i].flow or d[to]) continue; d[to]=d[u]+1; q.push(to); if(to==t) return 1; } } return 0; } int dinic(int now,int flow){ if(now==t) return flow; int res=flow; for(int i=head[now];i;i=edge[i].nxt){ int to=edge[i].to; if(d[to]!=d[now]+1 or !edge[i].flow) continue; int k=dinic(to,min(res,edge[i].flow)); if(!k) d[to]=0; edge[i].flow-=k;edge[i^1].flow+=k;res-=k; if(!res) return flow; } return flow-res; } int mf(){ int ans=0,flow=0; while(bfs()) while(flow=dinic(s,inf)) ans+=flow; return ans; } void dfs(int now){ printf("%d ",now>>1); for(int i=head[now];i;i=edge[i].nxt){ int to=edge[i].to; if(to==t or to==s or edge[i].flow) continue; dfs(to|1); } } #include<cmath> signed main(){ n=getint();cnt=1; s=0;t=5000;int now=0; for(int i=1;i;i++){ add(s,i<<1|1,1);add(i<<1|1,s,0); add(i<<1,t,1);add(t,i<<1,0); for(int j=sqrt(i)+1;j*j<(i<<1);j++) add(j*j-i<<1|1,i<<1,1),add(i<<1,j*j-i<<1|1,0); int k=mf(); if(!k){ if(now==n){ printf("%d\n",i-1); break; } else stk[++now]=i; } } for(int i=1;i<=n;i++) dfs(stk[i]<<1|1),puts(""); return 0; }