网络流之最大流板子题

在做最大流的题目之前,需要知道两个算法:EK与DINIC,但是鉴于我没有过多时间(特别懒),不想写基础知识与算法的推导,所以在此推荐两篇blog:(传送门1传送门2

板子题1:

  poj1273lougu2740codevs1993.此题很明显,一入眼就知道这是一个纯正的最大流板子题,没什么好写的,注意的是,poj中的题目是有多组数据的,然而题目中却没有写,让我一脸懵逼的WA了好几次(我好菜我好菜),洛谷和codevs则没有这个问题。不废话了,上代码!!
这是EK算法的:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cstdlib>
 7 #include<queue>
 8 using namespace std;
 9 int n,m,g[1005][1005],pre[2005],flow[2005];
10 queue <int> q;
11 int bfs(int s,int t)
12 {
13     while (!q.empty()) q.pop();
14     for (int i=1; i<=n; i++) pre[i]=-1;
15     pre[s]=0; q.push(s); flow[s]=20252025;
16     while (!q.empty()){
17         int x=q.front(); q.pop();
18         if (x==t) break;
19         for (int i=1; i<=n; i++)
20             if (g[x][i]>0 && pre[i]==-1){
21                 pre[i]=x;
22                 flow[i]=min(flow[x],g[x][i]);
23                 q.push(i);
24             }
25     }
26     if (pre[t]==-1) return -1;
27     else return flow[t];
28 }
29 int EK(int s,int t)
30 {
31     int increase=0,maxflow=0;
32     while ((increase=bfs(s,t))!=-1){
33         int k=t;
34         while (k!=s){
35             int xx=pre[k];
36             g[xx][k]-=increase;
37             g[k][xx]+=increase;
38             k=xx;
39         }
40         maxflow+=increase;
41     }
42     return maxflow;
43 }
44 int main()
45 {
46     while (~scanf("%d%d",&m,&n)){
47         memset(g,0,sizeof(g)); memset(flow,0,sizeof(flow));
48         for (int i=1; i<=m; i++){
49             int x,y,v;
50             scanf("%d%d%d",&x,&y,&v);
51             g[x][y]+=v;
52         }
53         int ans=EK(1,n);
54         cout<<ans<<endl;
55     }
56     return 0;
57 }

 

这是DINIC算法的:(未加多组数据)

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cstdlib>
 7 #include<queue>
 8 using namespace std;
 9 queue<int> q;
10 int n,m,x,y,z,maxflow,deep[505],vet[505],next[505],head[505],cur[505],dis[505],edgenum=-1;
11 const int INF=1e9;
12 void addedge(int u,int v,int t)
13 {
14     vet[++edgenum]=v;
15     next[edgenum]=head[u];
16     head[u]=edgenum;
17     dis[edgenum]=t;
18 }
19 bool bfs(int s,int t)
20 {
21     memset(deep,0x7f,sizeof(deep));
22     while (!q.empty()) q.pop();
23     for (int i=1; i<=n; i++) cur[i]=head[i];
24     deep[s]=0; q.push(s);
25     while (!q.empty()){
26         int x=q.front(); q.pop();
27         for (int e=head[x]; e!=-1; e=next[e])
28             if (deep[vet[e]]>INF && dis[e]){
29                 deep[vet[e]]=deep[x]+1;
30                 q.push(vet[e]);
31             }
32     }
33     if (deep[t]<INF) return true; else return false;
34 }
35 int dfs(int now,int t,int limit)
36 {
37     if (!limit || now==t) return limit;
38     int flow=0,f;
39     for (int e=cur[now]; e!=-1; e=next[e]){
40         cur[now]=e;
41         if ((deep[vet[e]]==(deep[now]+1)) && (f=dfs(vet[e],t,min(limit,dis[e])))){
42             flow+=f; limit-=f;
43             dis[e]-=f;
44             dis[e^1]+=f;
45             if (!limit) break;
46         }
47     }
48     return flow;
49 }
50 void dinic(int s,int t)
51 {
52     while (bfs(s,t)) maxflow+=dfs(s,t,INF);
53 }
54 int main()
55 {
56     scanf("%d%d",&m,&n);
57     memset(head,-1,sizeof(head));
58     for (int i=1; i<=m; i++){
59         int x,y,v;
60         scanf("%d%d%d",&x,&y,&v);
61         addedge(x,y,v); addedge(y,x,0);
62     }
63     dinic(1,n);
64     cout<<maxflow<<endl;
65     return 0;
66 }

板子题2:

  poj1459.这一道题目看一眼题面,稍加思考便可知此为最大流算法,我们只需要建立一个超级源点与超级汇点,将超级源点与发电站相连,超级汇点与用电处相连,跑一遍dinic便可。

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cstdlib>
 7 #include<queue>
 8 using namespace std;
 9 queue<int> q;
10 const int INF=1e9;
11 int vet[30005],next[30005],head[30005],dis[300005],cur[30005],edgenum=-1,n,np,nc,m,deep[30005],maxflow,sp,fp;
12 void addedge(int u,int v,int t)
13 {
14     vet[++edgenum]=v;
15     next[edgenum]=head[u];
16     head[u]=edgenum;
17     dis[edgenum]=t;
18 }
19 bool bfs(int s,int t)
20 {
21     for (int i=1; i<=n; i++) cur[i]=head[i];
22     memset(deep,0x7f,sizeof(deep)); deep[s]=0;
23     while (!q.empty()) q.pop(); q.push(s);
24     while (!q.empty()){
25         int x=q.front(); q.pop();
26         for (int e=head[x]; e!=-1; e=next[e])
27             if (deep[vet[e]]>INF && dis[e]){
28                 deep[vet[e]]=deep[x]+1;
29                 q.push(vet[e]);
30             }
31     }
32     if (deep[t]>INF) return false; else return true;
33 }
34 int dfs(int now,int t,int limit)
35 {
36     int flow=0,f;
37     if (!limit || now==t) return limit;
38     for (int e=cur[now]; e!=-1; e=next[e]){    
39         cur[now]=e;
40         if ((deep[vet[e]]==deep[now]+1) && (f=dfs(vet[e],t,min(limit,dis[e])))){
41             dis[e]-=f; limit-=f;
42             flow+=f; dis[e^1]+=f;
43             if (!limit) break;
44         }
45     }
46     return flow;
47 }
48 void dinic(int s,int t)
49 {
50     while (bfs(s,t)) maxflow+=dfs(s,t,INF);
51 }
52 int main()
53 {
54     while (~scanf("%d%d%d%d",&n,&np,&nc,&m)){
55         memset(head,-1,sizeof(head)); memset(next,-1,sizeof(next)); memset(dis,0,sizeof(dis)); edgenum=-1;
56         memset(cur,0,sizeof(cur)); char ch; maxflow=0;
57         for (int i=1; i<=m; i++){
58             int x,y,z;
59             cin>>ch>>x>>ch>>y>>ch>>z; x++; y++;
60             addedge(x,y,z); addedge(y,x,0);
61         }
62         sp=n+1; fp=n+2; n+=2;
63         for (int i=1; i<=np; i++){
64             int x,y;
65             cin>>ch>>x>>ch>>y; x++;
66             addedge(sp,x,y); addedge(x,sp,0);
67         }
68         for (int i=1; i<=nc; i++){
69             int x,y;
70             cin>>ch>>x>>ch>>y; x++;
71             addedge(x,fp,y); addedge(fp,x,0);
72         }
73         dinic(sp,fp);
74         cout<<maxflow<<endl;
75     }
76     return 0;
77 }

 

posted @ 2018-07-24 09:56  wangyh1008  阅读(820)  评论(0编辑  收藏  举报