码迷,mamicode.com
首页 > 其他好文 > 详细

[loj #6003]「网络流 24 题」魔术球 二分图最小路径覆盖,网络流

时间:2017-12-01 18:41:21      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:struct   cstring   enter   data   oid   yellow   接下来   --   ini   

#6003. 「网络流 24 题」魔术球

内存限制:256 MiB时间限制:1000 ms标准输入输出
题目类型:传统评测方式:Special Judge
上传者: 匿名

题目描述

假设有 n nn 根柱子,现要按下述规则在这 n nn 根柱子中依次放入编号为 1,2,3,4,? 1, 2, 3, 4, \cdots1,2,3,4,? 的球。

  1. 每次只能在某根柱子的最上面放球。
  2. 在同一根柱子中,任何 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 551n55

 

把每个柱子看成一条路径,跑最小路径覆盖。

 

技术分享图片
 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 }
View Code

 

[loj #6003]「网络流 24 题」魔术球 二分图最小路径覆盖,网络流

标签:struct   cstring   enter   data   oid   yellow   接下来   --   ini   

原文地址:http://www.cnblogs.com/wls001/p/7943664.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!