在做最大流的题目之前,需要知道两个算法:EK与DINIC,但是鉴于我没有过多时间(特别懒),不想写基础知识与算法的推导,所以在此推荐两篇blog:(传送门1、传送门2)
板子题1:
poj1273、lougu2740、codevs1993.此题很明显,一入眼就知道这是一个纯正的最大流板子题,没什么好写的,注意的是,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 }