网络流24题魔术球问题
Posted 蒟蒻ZJO :-)
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络流24题魔术球问题相关的知识,希望对你有一定的参考价值。
P1226 - 【网络流24题】魔术球问题
Description
假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球。
(1)每次只能在某根柱子的最上面放球。
(2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数。
试设计一个算法,计算出在n根柱子上最多能放多少个球。例如,在4 根柱子上最多可
放11个球。
′编程任务:
对于给定的n,计算在 n根柱子上最多能放多少个球。
Input
第1 行有 1个正整数n,表示柱子数。
Output
第一行是球数。
Sample Input
4
Sample Output
11
问题转化为最小路径覆盖的逆问题,从1开始枚举答案,跑最大流,计算出最小覆盖。
当最小覆盖>n时退出。
这里的实现有一个技巧:
在每次枚举时并不需要重新连边,只需要加上这次枚举的答案所连的边,然后在上次的残余网络上跑最大流就可以了。
1 #include<set> 2 #include<map> 3 #include<queue> 4 #include<stack> 5 #include<ctime> 6 #include<cmath> 7 #include<string> 8 #include<vector> 9 #include<cstdio> 10 #include<cstdlib> 11 #include<cstring> 12 #include<iostream> 13 #include<algorithm> 14 using namespace std; 15 struct data{ 16 int nex,to,w; 17 }e[700000]; 18 int head[10100],edge=-1,lev[10100]; 19 void add(int from,int to,int w){ 20 e[++edge].nex=head[from]; 21 e[edge].to=to; 22 e[edge].w=w; 23 head[from]=edge; 24 } 25 inline bool bfs(int s,int t){ 26 queue<int>q; 27 memset(lev,0,sizeof(lev)); 28 lev[s]=1; 29 q.push(s); 30 while(!q.empty()){ 31 int u=q.front(); 32 q.pop(); 33 for(int i=head[u];i!=-1;i=e[i].nex) 34 if(!lev[e[i].to] && e[i].w>0){ 35 lev[e[i].to]=lev[u]+1; 36 if(e[i].to==t) return 1; 37 else q.push(e[i].to); 38 } 39 } 40 return 0; 41 } 42 int dfs(int s,int t,int k){ 43 if(s==t) return k; 44 int rag=0; 45 for(int i=head[s];i!=-1;i=e[i].nex) 46 if(e[i].w>0 && lev[e[i].to]==lev[s]+1){ 47 int d=dfs(e[i].to,t,min(k-rag,e[i].w)); 48 e[i].w-=d; 49 e[i^1].w+=d; 50 rag+=d; 51 if(rag==k) return rag; 52 } 53 return rag; 54 } 55 int dinic(int s,int t){ 56 int flow=0; 57 while(bfs(s,t))flow+=dfs(s,t,1999999999); 58 return flow; 59 } 60 int main() 61 { 62 freopen("!.in","r",stdin); 63 freopen("!.out","w",stdout); 64 int n;scanf("%d",&n); 65 memset(head,-1,sizeof(head)); 66 int num=0,ans=0,s=0,t=10010; 67 while(1){ 68 num++,ans++; 69 for(int i=1;i<num;i++) 70 if(sqrt(i+num)==(int)(sqrt(i+num))) add(i,num+2000,1),add(num+2000,i,0); 71 add(s,num,1),add(num,s,0);add(num+2000,t,1),add(t,num+2000,0); 72 ans-=dinic(s,t); 73 if(ans>n) break; 74 } 75 printf("%d",num-1); 76 return 0; 77 }
以上是关于网络流24题魔术球问题的主要内容,如果未能解决你的问题,请参考以下文章