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 }

 

posted @ 2016-12-31 21:27  SilverNebula  阅读(195)  评论(0编辑  收藏  举报
AmazingCounters.com