网络流进阶

study from:

一篇很好的文章 拆点 拆边

https://www.cnblogs.com/tweetuzki/p/10422496.html

认真看解释,造一个简单、有代表性的图,画图辅助理解

Thieves

http://acm.hdu.edu.cn/showproblem.php?pid=3491

最小割=最大流

拆点(点有流量限制)

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <string>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <iostream>
  8 using namespace std;
  9 #define ll long long
 10 
 11 const int maxn=1e4+10;
 12 const int inf=1e9;
 13 
 14 struct node
 15 {
 16     int d,len;
 17     node *to,*opp;
 18 }*e[maxn];
 19 
 20 int s,t,q[maxn],dep[maxn];
 21 
 22 void addedge(int x,int y,int z)
 23 {
 24     node *p1,*p2;
 25     p1=new node();
 26     p2=new node();
 27 
 28     p1->d=y;
 29     p1->len=z;
 30     p1->opp=p2;
 31     p1->to=e[x];
 32     e[x]=p1;
 33 
 34     p2->d=x;
 35     p2->len=0;
 36     p2->opp=p1;
 37     p2->to=e[y];
 38     e[y]=p2;
 39 }
 40 
 41 bool bfs()
 42 {
 43     node *p;
 44     int head=0,tail=1,d,dd;
 45     memset(dep,0,sizeof(dep));
 46     dep[s]=1;
 47     q[1]=s;
 48     while (head<tail)
 49     {
 50         head++;
 51         d=q[head];
 52         p=e[d];
 53         while (p)
 54         {
 55             dd=p->d;
 56             if (!dep[dd] && p->len)
 57             {
 58                 q[++tail]=dd;
 59                 dep[dd]=dep[d]+1;
 60             }
 61             p=p->to;
 62         }
 63     }
 64     if (dep[t])
 65         return 1;
 66     return 0;
 67 }
 68 
 69 int dfs(int d,int add)
 70 {
 71     if (!add || d==t)
 72         return add;
 73     int totr=0,r,dd;
 74     node *p=e[d];
 75     while (p)
 76     {
 77         dd=p->d;
 78         if (dep[dd]==dep[d]+1 && (r=dfs(dd,min(add,p->len)))>0)
 79         {
 80             totr+=r;
 81             add-=r;
 82             p->len-=r;
 83             p->opp->len+=r;
 84         }
 85         p=p->to;
 86     }
 87     return totr;
 88 }
 89 
 90 int main()
 91 {
 92     int T,n,m,x,y,i,v,sum;
 93     scanf("%d",&T);
 94     while (T--)
 95     {
 96         scanf("%d%d%d%d",&n,&m,&s,&t);
 97         s+=n;
 98 //        t+=n;
 99         for (i=1;i<=2*n;i++)
100             e[i]=0;
101         for (i=1;i<=n;i++)
102         {
103             scanf("%d",&v);
104             addedge(i,i+n,v);
105         }
106         while (m--)
107         {
108             scanf("%d%d",&x,&y);
109             addedge(x+n,y,inf);
110             addedge(y+n,x,inf);
111         }
112         sum=0;
113         while (bfs())
114             sum+=dfs(s,inf);
115         printf("%d
",sum);
116     }
117     return 0;
118 }

类似的题目

Dining

http://poj.org/problem?id=3281

https://nanti.jisuanke.com/t/A1106

菜鸟物流的运输网络

way1

拆点,点i连点i+n,流量为1,从原点i入的边连接i+n,从原点i出的边连接点i。

源点mid,超级汇点连接s,t。

need边取反,即只适用于双向边

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <string>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <iostream>
  8 using namespace std;
  9 #define ll long long
 10 #include <queue>
 11 const int maxn=2e2+10;///*2
 12 const int inf=1e9;
 13 #include <assert.h>
 14 
 15 struct node
 16 {
 17     int d,len,cond;
 18     node *to,*opp;
 19 }*e[maxn];
 20 
 21 int n,ss,tt,mid,q[maxn],dep[maxn];
 22 
 23 void addedge(int x,int y,int z)
 24 {
 25     node *p1,*p2;
 26     p1=new node();
 27     p2=new node();
 28 
 29     p1->d=y;
 30     p1->len=z;
 31     p1->opp=p2;
 32     p1->to=e[x];
 33     e[x]=p1;
 34     p1->cond=0;
 35 
 36     p2->d=x;
 37     p2->len=0;
 38     p2->opp=p1;
 39     p2->to=e[y];
 40     e[y]=p2;
 41     p2->cond=1;
 42 }
 43 
 44 bool bfs()
 45 {
 46     node *p;
 47     int head=0,tail=1,d,dd;
 48     memset(dep,0,sizeof(dep));
 49     dep[ss]=1;
 50     q[1]=ss;
 51     while (head<tail)
 52     {
 53         head++;
 54         d=q[head];
 55         p=e[d];
 56         while (p)
 57         {
 58             dd=p->d;
 59             if (!dep[dd] && p->len)
 60             {
 61                 q[++tail]=dd;
 62                 dep[dd]=dep[d]+1;
 63             }
 64             p=p->to;
 65         }
 66     }
 67     if (dep[tt])
 68         return 1;
 69     return 0;
 70 }
 71 
 72 int dfs(int d,int add)
 73 {
 74 //    printf("%d %d
",d,add);
 75     if (!add || d==tt)
 76         return add;
 77     int totr=0,r,dd;
 78     node *p=e[d];
 79     while (p)
 80     {
 81         dd=p->d;
 82         if (dep[dd]==dep[d]+1 && (r=dfs(dd,min(add,p->len)))>0)
 83         {
 84             totr+=r;
 85             add-=r;
 86             p->len-=r;
 87             p->opp->len+=r;
 88         }
 89         p=p->to;
 90     }
 91     return totr;
 92 }
 93 
 94 void print(int x)
 95 {
 96     node *p=e[x];
 97     while (p)
 98     {
 99         if (p->cond && p->len)
100         {
101             x=p->d;
102             if (x!=mid)
103                 print(x);
104             break;
105         }
106         p=p->to;
107     }
108     if (x<=n)
109         printf("%d ",x);
110 }
111 
112 int main()
113 {
114     node *p;
115     int T,m,x,y,i,s,t,sum;
116     scanf("%d",&T);
117     while (T--)
118     {
119         scanf("%d%d",&n,&m);
120         scanf("%d%d%d",&s,&t,&mid);
121         ss=2*n+1;
122         tt=2*n+2;
123         for (i=1;i<=2*n+2;i++)
124             e[i]=0;
125         for (i=1;i<=n;i++)
126             if (i==mid)
127                 addedge(i,i+n,2);
128             else
129                 addedge(i,i+n,1);
130         addedge(2*n+1,mid,2);
131         addedge(s+n,2*n+2,1);
132         addedge(t+n,2*n+2,1);
133         while (m--)
134         {
135             scanf("%d%d",&x,&y);
136             addedge(x+n,y,1);
137             addedge(y+n,x,1);
138         }
139 
140         sum=0;
141         while (bfs())
142             sum+=dfs(ss,inf);
143 
144         x=s;
145         while (x!=mid)
146         {
147             if (x<=n)
148                 printf("%d ",x);
149             p=e[x];
150             while (p)
151             {
152                 if (p->cond && p->len)
153                 {
154                     x=p->d;
155                     break;
156                 }
157                 p=p->to;
158             }
159         }
160         print(t);
161         printf("%d
",t);
162     }
163     return 0;
164 }
165 /*
166 4
167 
168 5 5
169 1 5 3
170 1 2
171 2 3
172 3 4
173 4 5
174 5 1
175 
176 5 5
177 1 3 5
178 1 2
179 2 3
180 3 4
181 4 5
182 5 1
183 
184 3 3
185 1 2 3
186 2 1
187 2 3
188 3 1
189 
190 4 6
191 2 1 4
192 1 2
193 1 3
194 1 4
195 2 3
196 2 4
197 3 4
198 
199 10 10
200 5 3 10
201 1 2
202 2 3
203 3 4
204 4 5
205 5 6
206 6 7
207 7 8
208 8 9
209 9 10
210 10 1
211 
212 3 0
213 1 2 3
214 */

若求最短路径,用费用流。

但仍需要拆点,见以下情况。

同样的,不拆点求网络流,采用去环的方式也是不行的,见以下情况。

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <string>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <iostream>
  8 using namespace std;
  9 #define ll long long
 10 #include <queue>
 11 const int maxn=2e2+10;///*2
 12 const int inf=1e9;
 13 #include <assert.h>
 14 
 15 /*
 16 时间复杂度为O(N*E*k),其中K为最大流值。但时间上的期望时间复杂度为:O(A*E*K),其中A为所有顶点进队列的平均次数,可以证明A一般小于等于2。
 17 */
 18 
 19 struct node
 20 {
 21     int d,len,cost,cond;
 22     node *to,*opp;
 23 }*e[maxn],*pre[maxn];
 24 
 25 int ss,tt,dist[maxn],add[maxn],flow,fee;
 26 bool vis[maxn];
 27 int ans_p,pr[maxn];
 28 
 29 queue<int>st;
 30 
 31 void addedge(int x,int y,int len,int cost)
 32 {
 33     node *p1,*p2;
 34     p1=new node();
 35     p2=new node();
 36 
 37     p1->d=y;
 38     p1->len=len;
 39     p1->cost=cost;
 40     p1->opp=p2;
 41     p1->to=e[x];
 42     p1->cond=0;
 43     e[x]=p1;
 44 
 45     p2->d=x;
 46     p2->len=0;
 47     p2->cost=-cost;
 48     p2->opp=p1;
 49     p2->to=e[y];
 50     p2->cond=1;
 51     e[y]=p2;
 52 }
 53 
 54 void bfs()
 55 {
 56     node *p;
 57     int d,dd;
 58     while (1)
 59     {
 60         memset(dist,0x7f,sizeof(dist));
 61         dist[ss]=0;
 62         add[ss]=inf;
 63         add[tt]=0;
 64 
 65         st.push(ss);
 66         while (!st.empty())
 67         {
 68             d=st.front();
 69             st.pop();
 70             p=e[d];
 71             while (p)
 72             {
 73                 dd=p->d;
 74                 if (p->len && dist[dd]>dist[d]+p->cost)
 75                 {
 76                     dist[dd]=dist[d]+p->cost;
 77                     add[dd]=min(add[d],p->len);
 78                     pre[dd]=p->opp;
 79                     if (!vis[dd])
 80                     {
 81                         vis[dd]=1;
 82                         st.push(dd);
 83                     }
 84                 }
 85                 p=p->to;
 86             }
 87             vis[d]=0;
 88         }
 89 
 90         if (add[tt]==0)
 91             break;
 92 
 93         flow+=add[tt];
 94         fee+=add[tt]*dist[tt];
 95         d=tt;
 96         while (d!=ss)
 97         {
 98             pre[d]->len+=add[tt];
 99             pre[d]->opp->len-=add[tt];
100             d=pre[d]->d;
101         }
102     }
103 }
104 
105 int main()
106 {
107     node *p;
108     int T,n,m,x,y,i,mid,s,t;
109     scanf("%d",&T);
110     while (T--)
111     {
112         scanf("%d%d",&n,&m);
113         scanf("%d%d%d",&s,&t,&mid);
114         ss=2*n+1;
115         tt=2*n+2;
116         for (i=1;i<=2*n+2;i++)
117             e[i]=0;
118         for (i=1;i<=n;i++)
119             if (i==mid)
120                 addedge(i,i+n,2,1);
121             else
122                 addedge(i,i+n,1,1);
123         addedge(2*n+1,mid,2,1);
124         addedge(s+n,2*n+2,1,1);
125         addedge(t+n,2*n+2,1,1);
126         while (m--)
127         {
128             scanf("%d%d",&x,&y);
129             addedge(x+n,y,1,1);
130             addedge(y+n,x,1,1);
131         }
132 
133         flow=0,fee=0;
134         bfs();
135 
136 //        printf("data=%d %d %d
",s,t,mid);
137 
138         if (flow!=2)
139         {
140             printf("-1
");
141             continue;
142         }
143 
144         ans_p=0;
145         x=s;
146         while (x!=mid)
147         {
148             if (x<=n)
149                 pr[++ans_p]=x;
150             p=e[x];
151             while (p)
152             {
153                 if (p->cond && p->len)
154                 {
155                     x=p->d;
156                     break;
157                 }
158                 p=p->to;
159             }
160         }
161         for (i=1;i<=ans_p;i++)
162             printf("%d ",pr[i]);
163 
164         ans_p=0;
165         x=t;
166         while (x!=mid)
167         {
168             if (x<=n)
169                 pr[++ans_p]=x;
170             p=e[x];
171             while (p)
172             {
173                 if (p->cond && p->len)
174                 {
175                     x=p->d;
176                     break;
177                 }
178                 p=p->to;
179             }
180         }
181         printf("%d",mid);
182         for (i=ans_p;i>=1;i--)
183             printf(" %d",pr[i]);
184         printf("
");
185     }
186     return 0;
187 }
188 /*
189 5
190 
191 5 5
192 1 5 3
193 1 2
194 2 3
195 3 4
196 4 5
197 5 1
198 
199 5 5
200 1 3 5
201 1 2
202 2 3
203 3 4
204 4 5
205 5 1
206 
207 3 3
208 1 2 3
209 2 1
210 2 3
211 3 1
212 
213 4 6
214 2 1 4
215 1 2
216 1 3
217 1 4
218 2 3
219 2 4
220 3 4
221 
222 10 10
223 5 3 10
224 1 2
225 2 3
226 3 4
227 4 5
228 5 6
229 6 7
230 7 8
231 8 9
232 9 10
233 10 1
234 
235 3 0
236 1 2 3
237 
238 5 6
239 2 1 4
240 1 2
241 2 4
242 4 5
243 4 3
244 5 1
245 3 1
246 
247 */

 

错误代码1

网络流不拆点删环

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <string>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <iostream>
  8 using namespace std;
  9 #define ll long long
 10 #include <queue>
 11 const int maxn=1e2+10;
 12 const int inf=1e9;
 13 #include <assert.h>
 14 
 15 /*
 16 不拆点,网络规模减少一半
 17 
 18 输出结果,去环 O(n)
 19 或者用费用流 每条边cost=-1,求最短的路径
 20 费用流时间复杂度?
 21 dinic时间复杂度?
 22 */
 23 
 24 struct node
 25 {
 26     int d,len,cond,visit;
 27     node *to,*opp;
 28 }*e[maxn];
 29 
 30 int ss,tt,mid,q[maxn],dep[maxn];
 31 int ans_p,pr[maxn],pre[maxn];
 32 
 33 void addedge(int x,int y,int z)
 34 {
 35     node *p1,*p2;
 36     p1=new node();
 37     p2=new node();
 38 
 39     p1->d=y;
 40     p1->len=z;
 41     p1->opp=p2;
 42     p1->to=e[x];
 43     e[x]=p1;
 44     p1->cond=0;
 45 
 46     p2->d=x;
 47     p2->len=0;
 48     p2->opp=p1;
 49     p2->to=e[y];
 50     e[y]=p2;
 51     p2->cond=1;
 52 }
 53 
 54 bool bfs()
 55 {
 56     node *p;
 57     int head=0,tail=1,d,dd;
 58     memset(dep,0,sizeof(dep));
 59     dep[ss]=1;
 60     q[1]=ss;
 61     while (head<tail)
 62     {
 63         head++;
 64         d=q[head];
 65         p=e[d];
 66         while (p)
 67         {
 68             dd=p->d;
 69             if (!dep[dd] && p->len)
 70             {
 71                 q[++tail]=dd;
 72                 dep[dd]=dep[d]+1;
 73             }
 74             p=p->to;
 75         }
 76     }
 77     if (dep[tt])
 78         return 1;
 79     return 0;
 80 }
 81 
 82 int dfs(int d,int add)
 83 {
 84     if (!add || d==tt)
 85         return add;
 86     int totr=0,r,dd;
 87     node *p=e[d];
 88     while (p)
 89     {
 90         dd=p->d;
 91         if (dep[dd]==dep[d]+1 && (r=dfs(dd,min(add,p->len)))>0)
 92         {
 93             totr+=r;
 94             add-=r;
 95             p->len-=r;
 96             p->opp->len+=r;
 97         }
 98         p=p->to;
 99     }
100     return totr;
101 }
102 
103 void print(int x)
104 {
105     node *p=e[x];
106     while (p)
107     {
108         if (p->cond && p->len)
109         {
110             x=p->d;
111             if (x!=mid)
112                 print(x);
113             break;
114         }
115         p=p->to;
116     }
117     printf("%d ",x);
118 }
119 
120 int main()
121 {
122     node *p;
123     int T,n,m,x,y,i,s,t,sum;
124     scanf("%d",&T);
125     while (T--)
126     {
127         scanf("%d%d",&n,&m);
128         scanf("%d%d%d",&s,&t,&mid);
129         ss=n+1;
130         tt=n+2;
131         for (i=1;i<=n+2;i++)
132             e[i]=0;
133         addedge(n+1,mid,2);
134         addedge(s,n+2,1);
135         addedge(t,n+2,1);
136         while (m--)
137         {
138             scanf("%d%d",&x,&y);
139             addedge(x,y,1);
140             addedge(y,x,1);
141         }
142 
143         sum=0;
144         while (bfs())
145             sum+=dfs(ss,inf);
146 
147 //        assert(sum==2);
148 
149         ///有可能出现环结构 x->y->z->x or others, 去环
150         memset(pre,0,sizeof(pre));
151         ans_p=0;
152         x=s;
153         while (x!=mid)
154         {
155             pr[++ans_p]=x;
156             p=e[x];
157             while (p)
158             {
159                 if (p->cond && p->len && !p->visit)
160                 {
161                     x=p->d;
162                     p->visit=1;
163                     break;
164                 }
165                 p=p->to;
166             }
167             if (pre[x])
168                 ans_p=pre[x];
169             else
170                 pre[x]=ans_p+1;
171         }
172         for (i=1;i<=ans_p;i++)
173             printf("%d ",pr[i]);
174 
175         memset(pre,0,sizeof(pre));
176         ans_p=0;
177         x=t;
178         while (x!=mid)
179         {
180             pr[++ans_p]=x;
181             p=e[x];
182             while (p)
183             {
184                 if (p->cond && p->len && !p->visit)
185                 {
186                     x=p->d;
187                     p->visit=1;
188                     break;
189                 }
190                 p=p->to;
191             }
192             if (pre[x])
193                 ans_p=pre[x];
194             else
195                 pre[x]=ans_p+1;
196         }
197         printf("%d",mid);
198         for (i=ans_p;i>=1;i--)
199             printf(" %d",pr[i]);
200         printf("
");
201 
202 //        ///100*99=9900 *10 sometimes need
203 //        node *pp;
204 //        for (i=1;i<=n+2;i++)
205 //        {
206 //            p=e[i];
207 //            while (p)
208 //            {
209 //                p->visit=0;
210 //                pp=p;
211 //                p=p->to;
212 //                free(pp);
213 //            }
214 //        }
215     }
216     return 0;
217 }
218 /*
219 5
220 
221 5 5
222 1 5 3
223 1 2
224 2 3
225 3 4
226 4 5
227 5 1
228 
229 5 5
230 1 3 5
231 1 2
232 2 3
233 3 4
234 4 5
235 5 1
236 
237 3 3
238 1 2 3
239 2 1
240 2 3
241 3 1
242 
243 4 6
244 2 1 4
245 1 2
246 1 3
247 1 4
248 2 3
249 2 4
250 3 4
251 
252 10 10
253 5 3 10
254 1 2
255 2 3
256 3 4
257 4 5
258 5 6
259 6 7
260 7 8
261 8 9
262 9 10
263 10 1
264 
265 
266 
267 3 0
268 1 2 3
269 
270 
271 1
272 5 6
273 2 1 4
274 1 2
275 2 4
276 4 5
277 4 3
278 5 1
279 3 1
280 */

错误代码2

费用流不拆点

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <string>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <iostream>
  8 using namespace std;
  9 #define ll long long
 10 #include <queue>
 11 const int maxn=1e2+10;
 12 const int inf=1e9;
 13 #include <assert.h>
 14 
 15 /*
 16 时间复杂度为O(N*E*k),其中K为最大流值。但时间上的期望时间复杂度为:O(A*E*K),其中A为所有顶点进队列的平均次数,可以证明A一般小于等于2。
 17 */
 18 
 19 struct node
 20 {
 21     int d,len,cost,cond;
 22     node *to,*opp;
 23 }*e[maxn],*pre[maxn];
 24 
 25 int ss,tt,dist[maxn],add[maxn],flow,fee;
 26 bool vis[maxn];
 27 int ans_p,pr[maxn];
 28 
 29 queue<int>st;
 30 
 31 void addedge(int x,int y,int len,int cost)
 32 {
 33     node *p1,*p2;
 34     p1=new node();
 35     p2=new node();
 36 
 37     p1->d=y;
 38     p1->len=len;
 39     p1->cost=cost;
 40     p1->opp=p2;
 41     p1->to=e[x];
 42     p1->cond=0;
 43     e[x]=p1;
 44 
 45     p2->d=x;
 46     p2->len=0;
 47     p2->cost=-cost;
 48     p2->opp=p1;
 49     p2->to=e[y];
 50     p2->cond=1;
 51     e[y]=p2;
 52 }
 53 
 54 void bfs()
 55 {
 56     node *p;
 57     int d,dd;
 58     while (1)
 59     {
 60         memset(dist,0x7f,sizeof(dist));
 61         dist[ss]=0;
 62         add[ss]=inf;
 63         add[tt]=0;
 64 
 65         st.push(ss);
 66         while (!st.empty())
 67         {
 68             d=st.front();
 69             st.pop();
 70             p=e[d];
 71             while (p)
 72             {
 73                 dd=p->d;
 74                 if (p->len && dist[dd]>dist[d]+p->cost)
 75                 {
 76                     dist[dd]=dist[d]+p->cost;
 77                     add[dd]=min(add[d],p->len);
 78                     pre[dd]=p->opp;
 79                     if (!vis[dd])
 80                     {
 81                         vis[dd]=1;
 82                         st.push(dd);
 83                     }
 84                 }
 85                 p=p->to;
 86             }
 87             vis[d]=0;
 88         }
 89 
 90         if (add[tt]==0)
 91             break;
 92 
 93         flow+=add[tt];
 94         fee+=add[tt]*dist[tt];
 95         d=tt;
 96         while (d!=ss)
 97         {
 98             pre[d]->len+=add[tt];
 99             pre[d]->opp->len-=add[tt];
100             d=pre[d]->d;
101         }
102     }
103 }
104 
105 int main()
106 {
107     node *p;
108     int T,n,m,x,y,i,mid,s,t;
109     scanf("%d",&T);
110     while (T--)
111     {
112         scanf("%d%d",&n,&m);
113         scanf("%d%d%d",&s,&t,&mid);
114         ss=n+1;
115         tt=n+2;
116         for (i=1;i<=n+2;i++)
117             e[i]=0;
118         addedge(n+1,mid,2,1);
119         addedge(s,n+2,1,1);
120         addedge(t,n+2,1,1);
121         while (m--)
122         {
123             scanf("%d%d",&x,&y);
124             if (x!=s && x!=t)
125                 addedge(x,y,1,1);
126             if (y!=s && y!=t)
127                 addedge(y,x,1,1);
128         }
129 
130         flow=0,fee=0;
131         bfs();
132 
133 //        printf("data=%d %d %d
",s,t,mid);
134 
135         if (flow!=2)
136         {
137             printf("-1
");
138             continue;
139         }
140 
141         ans_p=0;
142         x=s;
143         while (x!=mid)
144         {
145             pr[++ans_p]=x;
146             p=e[x];
147             while (p)
148             {
149                 if (p->cond && p->len)
150                 {
151                     x=p->d;
152                     break;
153                 }
154                 p=p->to;
155             }
156         }
157         for (i=1;i<=ans_p;i++)
158             printf("%d ",pr[i]);
159 
160         ans_p=0;
161         x=t;
162         while (x!=mid)
163         {
164             pr[++ans_p]=x;
165             p=e[x];
166             while (p)
167             {
168                 if (p->cond && p->len)
169                 {
170                     x=p->d;
171                     break;
172                 }
173                 p=p->to;
174             }
175         }
176         printf("%d",mid);
177         for (i=ans_p;i>=1;i--)
178             printf(" %d",pr[i]);
179         printf("
");
180     }
181     return 0;
182 }
183 /*
184 5
185 
186 5 5
187 1 5 3
188 1 2
189 2 3
190 3 4
191 4 5
192 5 1
193 
194 5 5
195 1 3 5
196 1 2
197 2 3
198 3 4
199 4 5
200 5 1
201 
202 3 3
203 1 2 3
204 2 1
205 2 3
206 3 1
207 
208 4 6
209 2 1 4
210 1 2
211 1 3
212 1 4
213 2 3
214 2 4
215 3 4
216 
217 10 10
218 5 3 10
219 1 2
220 2 3
221 3 4
222 4 5
223 5 6
224 6 7
225 7 8
226 8 9
227 9 10
228 10 1
229 
230 3 0
231 1 2 3
232 
233 5 6
234 2 1 4
235 1 2
236 2 4
237 4 5
238 4 3
239 5 1
240 3 1
241 
242 */

构造时出现的困难:

1.费用流 不能有负环 从而无法设置更大的负值,从而决定一定要走哪条边

2.上下界可行流

想过设置mid->mid+n(可以再加上s->s+n和t->t+n)下界为1

但是无法做到流形成一条路径

如d->d+n下界为1,点d与点p相连,则可以为

sss->d+n->p->p+n->d->ttt

可以判断dfs形成的解是否为一条从s到t的链,

但是dfs形成的解太多,时间复杂度无法降下来。

由于无法解决这个问题,那么进一步的想法也没有意义了:

设置所有的点 d->d+n,使所有点从必须遍历,随机选择一个起点,终点为其中一个与起点相连的点,求网络流,解为哈密顿回路。

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <string>
  6 #include <algorithm>
  7 #include <set>
  8 #include <map>
  9 #include <queue>
 10 #include <iostream>
 11 using namespace std;
 12 
 13 #define ll long long
 14 
 15 const int maxn=2e2+10;
 16 const int maxm=1e4;
 17 const int inf=1e9;
 18 const double eps=1e-8;
 19 
 20 struct node
 21 {
 22     int d,len,cond;
 23     node *to,*opp;
 24 }*e[maxn];
 25 
 26 int dif[maxn],dep[maxn],q[maxn],n,low[maxm],ss,tt,st,en;
 27 
 28 void addedge(int x,int y,int z)
 29 {
 30 //    printf("===%d %d %d
",x,y,z);
 31 
 32     node *p1,*p2;
 33     p1=new node();
 34     p2=new node();
 35 
 36     p1->d=y;
 37     p1->len=z;
 38     p1->opp=p2;
 39     p1->to=e[x];
 40     e[x]=p1;
 41     p1->cond=0;
 42 
 43     p2->d=x;
 44     p2->len=0;
 45     p2->opp=p1;
 46     p2->to=e[y];
 47     e[y]=p2;
 48     p2->cond=1;
 49 }
 50 
 51 bool bfs()
 52 {
 53     node *p;
 54     int head=0,tail=1,d,dd;
 55     memset(dep,0,sizeof(dep));
 56     dep[st]=1;
 57     q[1]=st;
 58     while (head<tail)
 59     {
 60         head++;
 61         d=q[head];
 62         p=e[d];
 63         while (p)
 64         {
 65             dd=p->d;
 66             if (!dep[dd] && p->len)
 67             {
 68                 q[++tail]=dd;
 69                 dep[dd]=dep[d]+1;
 70             }
 71             p=p->to;
 72         }
 73     }
 74     if (dep[en])
 75         return 1;
 76     return 0;
 77 }
 78 
 79 int dfs(int d,int add)
 80 {
 81     if (!add || d==en)
 82         return add;
 83     int totr=0,r,dd;
 84     node *p=e[d];
 85     while (p)
 86     {
 87         dd=p->d;
 88         if (dep[dd]==dep[d]+1 && (r=dfs(dd,min(add,p->len)))>0)
 89         {
 90             totr+=r;
 91             add-=r;
 92             p->len-=r;
 93             p->opp->len+=r;
 94         }
 95         p=p->to;
 96     }
 97     return totr;
 98 }
 99 
100 int main()
101 {
102     node *p;
103     int T,n,m,x,y,i,mid,s,t,sum,sss,ttt;
104     scanf("%d",&T);
105     while (T--)
106     {
107         scanf("%d%d",&n,&m);
108         scanf("%d%d%d",&s,&t,&mid);
109 
110         for (i=1;i<=2*n+4;i++)
111             e[i]=0;
112         sss=2*n+3;
113         ttt=2*n+4;
114         ss=2*n+1;
115         tt=2*n+2;
116         addedge(ss,s,1);
117         addedge(t+n,tt,1);
118         for (i=1;i<=n;i++)
119             if (i==mid || i==s || i==t)
120                 addedge(i,i+n,1-1);
121             else
122                 addedge(i,i+n,1);
123 
124         addedge(sss,mid+n,1);///
125         addedge(mid,ttt,1);
126 
127         addedge(sss,s+n,1);///
128         addedge(s,ttt,1);
129 
130         addedge(sss,t+n,1);///
131         addedge(t,ttt,1);
132 
133         int tot=1;
134         while (m--)
135         {
136             scanf("%d%d",&x,&y);
137             addedge(x+n,y,1);
138             addedge(y+n,x,1);
139         }
140 
141         addedge(tt,ss,inf);
142 
143         st=sss,en=ttt;
144         sum=0;
145         while (bfs())
146             sum+=dfs(st,inf);
147 //        if (sum==tot)
148 //        {
149 //            sum=0;
150 //            st=ss,en=tt;
151 //            while (bfs())
152 //                sum+=dfs(st,inf);
153 
154             x=s;
155             while (x!=mid)
156             {
157                 if (x<=n)
158                     printf("%d ",x);
159                 p=e[x];
160                 while (p)
161                 {
162                     if (!p->cond && p->opp->len)
163                         break;
164                     p=p->to;
165                 }
166             }
167             ///
168             x=mid+n;
169             while (x!=t)
170             {
171                 if (x<=n)
172                     printf("%d ",x);
173                 p=e[x];
174                 while (p)
175                 {
176                     if (!p->cond && p->opp->len)
177                         break;
178                     p=p->to;
179                 }
180             }
181             printf("%d
",t);
182 
183 //        }
184 //        else
185 //            printf("please go home to sleep");
186     }
187     return 0;
188 }
189 /*
190 4 3 1 4
191 2 3 2 3
192 1 2 0 100
193 3 4 0 100
194 
195 4 3 1 4
196 2 3 0 3
197 1 2 0 100
198 3 4 0 100
199 */

造数据:

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <string>
 5 #include <cmath>
 6 #include <algorithm>
 7 #include <iostream>
 8 using namespace std;
 9 #define ll long long
10 #include <time.h>
11 
12 const int maxn=1e2+10;
13 
14 bool vis[maxn][maxn];
15 int px[maxn*maxn],py[maxn*maxn];
16 
17 int main()
18 {
19     int t,n,m,x,y,z,i;
20     srand(time(NULL));
21     FILE *in=fopen("1.in","w");
22     t=1000;
23     fprintf(in,"%d
",t);
24     while (t--)
25     {
26         do
27         {
28             n=rand()%100+1;
29         }
30         while (n<=2);
31         m=rand()%(n*(n-1)/2)+1;
32 
33         x=rand()%n+1;
34         do
35             y=rand()%n+1;
36         while (y==x);
37         do
38             z=rand()%n+1;
39         while (z==x || z==y);
40 
41         fprintf(in,"%d %d
",n,m);
42         fprintf(in,"%d %d %d
",x,y,z);
43 
44 
45         memset(vis,0,sizeof(vis));
46         for (i=1;i<=m;)
47         {
48             x=rand()%n+1;
49             do
50                 y=rand()%n+1;
51             while (y==x);
52             if (!vis[x][y])
53             {
54                 px[i]=x,py[i]=y;
55                 i++;
56             }
57         }
58         for (i=1;i<=m;i++)
59             fprintf(in,"%d %d
",px[i],py[i]);
60         fprintf(in,"
");
61     }
62     fclose(in);
63     return 0;
64 }

练习题:

P2045 方格取数加强版

https://www.luogu.org/problemnew/show/P2045

获得最大值需要的最少部分(自己造的!)

网络流+二分

原文地址:https://www.cnblogs.com/cmyg/p/11053148.html