网络流之最大流板子题
在做最大流的题目之前,需要知道两个算法: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 }