[loj #6003]「网络流 24 题」魔术球 二分图最小路径覆盖,网络流
Posted wls001
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[loj #6003]「网络流 24 题」魔术球 二分图最小路径覆盖,网络流相关的知识,希望对你有一定的参考价值。
#6003. 「网络流 24 题」魔术球
内存限制:256 MiB时间限制:1000 ms标准输入输出
题目类型:传统评测方式:Special Judge
上传者: 匿名
题目描述
假设有 n nn 根柱子,现要按下述规则在这 n nn 根柱子中依次放入编号为 1,2,3,4,? 1, 2, 3, 4, \cdots1,2,3,4,? 的球。
- 每次只能在某根柱子的最上面放球。
- 在同一根柱子中,任何 2 22 个相邻球的编号之和为完全平方数。
试设计一个算法,计算出在 n nn 根柱子上最多能放多少个球。
输入格式
文件第 1 11 行有 1 11 个正整数 n nn,表示柱子数。
输出格式
第一行是球数。接下来的 n nn 行,每行是一根柱子上的球的编号。
样例
样例输入
4
样例输出
11
1 8
2 7 9
3 6 10
4 5 11
数据范围与提示
1≤n≤55 1 \leq n \leq 551≤n≤55
把每个柱子看成一条路径,跑最小路径覆盖。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<cmath> 6 #include<algorithm> 7 using namespace std; 8 struct data { 9 int to,next,f; 10 }e[100005]; 11 int head[5005],cnt; 12 void add(int u,int v,int f){e[cnt].to=v;e[cnt].next=head[u];e[cnt].f=f;head[u]=cnt++;} 13 int n,m,s,t; 14 bool vis[5005]; 15 int q[5005],dis[5005]; 16 bool bfs() { 17 memset(dis,-57,sizeof(dis)); 18 int h=0,tail=1; 19 q[h]=t; 20 dis[t]=0; 21 while(h!=tail) { 22 int now=q[h++];if(h==5000) h=0; 23 for(int i=head[now];i>=0;i=e[i].next) { 24 if(dis[e[i].to]>-100000||!e[i^1].f) continue; 25 dis[e[i].to]=dis[now]-1; 26 q[tail++]=e[i].to;if(tail==5000) tail=0; 27 } 28 } 29 return dis[s]>=-100000; 30 } 31 int dfs(int now,int a) { 32 int f=0,flow=0; 33 if(now==t) return a; 34 for(int i=head[now];i>=0;i=e[i].next) { 35 int to=e[i].to; 36 if(dis[to]==dis[now]+1&&e[i].f>0) { 37 f=dfs(to,min(a,e[i].f)); 38 flow+=f; 39 e[i].f-=f; 40 e[i^1].f+=f; 41 a-=f; 42 if(a==0) break; 43 } 44 } 45 return flow; 46 } 47 int num=0; 48 int ans=0; 49 int sum=0; 50 int dinic() { 51 while(bfs()) { 52 sum+=dfs(s,2147483647); 53 } 54 return num-sum; 55 } 56 57 bool work() { 58 num++; 59 add(s,num,1);add(num,s,0);add(num+2500,t,1);add(t,num+2500,0); 60 for(int i=1;i<num;i++) { 61 if(sqrt(i+num)==(int)sqrt(i+num)) add(num,i+2500,1),add(i+2500,num,0); 62 } 63 if(dinic()<=n) return 1; 64 else return 0; 65 } 66 void pout(int x) { 67 vis[x]=1; 68 printf("%d ",x); 69 for(int i=head[x+2500];i>=0;i=e[i].next) { 70 if(e[i].f==1&&!vis[e[i].to]){pout(e[i].to);return;} 71 } 72 return; 73 } 74 int main() { 75 memset(head,-1,sizeof(head)); 76 scanf("%d",&n); 77 s=0,t=5001; 78 while(work()) ; 79 num--; 80 printf("%d\n",num); 81 memset(vis,0,sizeof(vis)); 82 vis[s]=vis[t]=1; 83 for(int i=1;i<=num;i++) { 84 if(!vis[i]){pout(i);printf("\n");} 85 } 86 }
以上是关于[loj #6003]「网络流 24 题」魔术球 二分图最小路径覆盖,网络流的主要内容,如果未能解决你的问题,请参考以下文章