COGS396. [网络流24题]魔术球问题(简化版
问题描述:
假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球。
(1)每次只能在某根柱子的最上面放球。
(2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数。
试设计一个算法,计算出在n根柱子上最多能放多少个球。例如,在4 根柱子上最多可
放11个球。
´编程任务:
对于给定的n,计算在 n根柱子上最多能放多少个球。
´数据输入:
文件第1 行有 1个正整数n,表示柱子数。
´结果输出:
文件的第一行是球数。
数据规模
n<=60 保证答案小于1600
输入文件示例
4
输出文件示例
11
方案如下
1 8
2 7 9
3 6 10
4 5 11
每一行表示一个柱子上的球
网络流 最小路径覆盖
从1到1600枚举放的球数量。
将表示每个球的点拆分出入点和
从源点S到每个球入点连边,每个球出点到汇点连边,能放在一起的球之间连边(编号小的入点到编号大的出点)。
球数i-最大流答案m<=柱子数n时,可行。
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 #include<queue> 9 using namespace std; 10 const int INF=1e9; 11 const int mxn=3510; 12 int read(){ 13 int x=0,f=1;char ch=getchar(); 14 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 15 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 16 return x*f; 17 } 18 struct edge{ 19 int v,nxt,f; 20 }e[mxn*50]; 21 int hd[mxn],mct=1; 22 void add_edge(int u,int v,int c){ 23 e[++mct].v=v;e[mct].nxt=hd[u];e[mct].f=c;hd[u]=mct;return; 24 } 25 void insert(int u,int v,int c){ 26 add_edge(u,v,c);add_edge(v,u,0);return; 27 } 28 int n,m,S,T; 29 int d[mxn]; 30 bool BFS(){ 31 memset(d,0,sizeof d); 32 queue<int>q; 33 q.push(S); 34 d[S]=1; 35 while(!q.empty()){ 36 int u=q.front();q.pop(); 37 for(int i=hd[u];i;i=e[i].nxt){ 38 int v=e[i].v; 39 if(e[i].f && !d[v]){ 40 d[v]=d[u]+1; 41 q.push(v); 42 } 43 } 44 } 45 return d[T]; 46 } 47 int DFS(int u,int lim){ 48 if(u==T)return lim; 49 int tmp,f=0; 50 for(int i=hd[u];i;i=e[i].nxt){ 51 int v=e[i].v; 52 if(d[v]==d[u]+1 && e[i].f){ 53 tmp=DFS(v,min(lim,e[i].f)); 54 e[i].f-=tmp; 55 e[i^1].f+=tmp; 56 f+=tmp; 57 lim-=tmp; 58 if(!lim)return f; 59 } 60 } 61 d[u]=0; 62 return f; 63 } 64 int Dinic(){ 65 int res=0; 66 while(BFS())res+=DFS(S,INF); 67 return res; 68 } 69 int main(){ 70 freopen("balla.in","r",stdin); 71 freopen("balla.out","w",stdout); 72 int i,j; 73 n=read();m=0; 74 S=0,T=3201; 75 for(i=1;i<=1600;i++){ 76 insert(S,i*2-1,1); 77 insert(i*2,T,1); 78 for(j=1;j<i;j++){ 79 int t=sqrt(j+i); 80 if(t*t==j+i){ 81 insert(j*2-1,i*2,1); 82 } 83 } 84 // 85 m+=Dinic(); 86 if(i-m>n)break; 87 } 88 printf("%d\n",i-1); 89 return 0; 90 }
本文为博主原创文章,转载请注明出处。