网络流24题之魔术球问题

其实每个柱子就相当于最小路径覆盖中的一根柱子。

我们要在有n条路径的最小覆盖中加尽量多的点。

所以我们枚举答案加边即可。

By:大奕哥

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<queue>
 7 #include<vector>
 8 #include<cmath>
 9 using namespace std;
10 const int N=100005;
11 int n,m,s=0,t=100000,head[N],d[N],vis[N],w[N],cnt=-1;
12 inline 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<<1)+(x<<3)+ch-'0',ch=getchar();
16     return x*f;
17 }
18 struct node{
19     int to,nex,w;
20 }e[N<<1];
21 void add(int x,int y,int w)
22 {
23     e[++cnt].to=y;e[cnt].w=w;e[cnt].nex=head[x];head[x]=cnt;
24     e[++cnt].to=x;e[cnt].w=0;e[cnt].nex=head[y];head[y]=cnt;
25 }
26 queue<int>q;
27 bool bfs(int x,int y)
28 {
29     memset(d,-1,sizeof(d));
30     d[x]=0;q.push(x);
31     while(!q.empty())
32     {
33         int x=q.front();q.pop();
34         for(int i=head[x];i!=-1;i=e[i].nex)
35         {
36             int y=e[i].to;
37             if(!e[i].w||d[y]!=-1)continue;
38             d[y]=d[x]+1;
39             q.push(y);
40         }
41     }
42     return d[y]!=-1;
43 }
44 int dfs(int x,int w,int yy)
45 {
46     if(!w||x==yy)return w;
47     int s=0;
48     for(int i=head[x];i!=-1;i=e[i].nex)
49     {
50         int y=e[i].to;
51         if(!e[i].w||d[y]!=d[x]+1)continue;
52         int flow=dfs(y,min(w-s,e[i].w),yy);
53         if(!flow){
54             d[y]=-1;continue;
55         }
56         e[i].w-=flow;e[i^1].w+=flow;
57         vis[x]=y;s+=flow;
58         if(s==w)return s;
59     }
60     return s;
61 }
62 int dinic()
63 {
64     int ans=0;
65     while(bfs(s,t)){
66         ans+=dfs(s,1e9,t);
67     }
68     return ans;
69 }
70 int main()
71 {
72     n=read();
73     memset(head,-1,sizeof(head));
74     int ans=0,num=0,x,y;
75     while(ans<=n)
76     {
77         num++;
78         add(s,num<<1,1);add(num<<1|1,t,1);
79         for(int i=sqrt(num)+1;i*i<(num<<1);++i)
80         add((i*i-num)<<1,num<<1|1,1);
81         if(!dinic())w[++ans]=num;
82     }
83     printf("%d\n",num-1);
84     for(int i=1;i<=n;++i)
85     {
86         x=w[i];x<<=1;
87         while(x)
88         {
89             if((x&1))x^=1;
90             printf("%d ",x>>1);
91             y=vis[x];
92             vis[x]=0;
93             x=y;
94         }
95         printf("\n");
96     }
97     return 0;
98 }

 

posted @ 2018-01-28 13:00  大奕哥&VANE  阅读(125)  评论(0编辑  收藏  举报