题意:
在一个网络图中有n个点,其中有np个发电站,nc个用户,m条电线;每个发电站,用户,和电线都对应有一个最大的电流;让求出该网络中最大的电流;
添加一个源点为(0)和一个汇点(n+1),源点与发电站相连,电流量为发电站的最大电流;用户与汇点相连,电流量为用户需要的最大电流。
EK算法模版:
10944604 | xinghan0219 | 1459 | Accepted | 768K | 625MS | G++ | 1290B | 2012-10-22 23:17:50 |
View Code
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <algorithm> 6 7 using namespace std; 8 9 #define inf 0x7ffffff 10 #define Min(x,y) (x>y?y:x) 11 #define MAXN 105 12 int n,np,nc,m; 13 int flow[MAXN][MAXN]; 14 int maxflow; 15 int st,en; 16 int a[MAXN]; 17 int cap[MAXN][MAXN]; 18 int pre[MAXN]; 19 20 int EK() 21 { 22 queue<int>q; 23 while(!q.empty()) q.pop(); 24 memset(flow,0,sizeof(flow)); 25 maxflow=0; 26 while(1) 27 { 28 memset(a,0,sizeof(a)); 29 a[st]=inf; 30 q.push(st); 31 while(!q.empty()) 32 { 33 int u=q.front();q.pop(); 34 for(int v=0;v<=n+1;v++) 35 if(!a[v] && cap[u][v]>flow[u][v]) 36 { 37 pre[v]=u;q.push(v); 38 a[v]=Min(a[u],cap[u][v]-flow[u][v]); 39 } 40 } 41 if(a[en]==0) break; 42 for(int u=en;u!=st;u=pre[u]) 43 { 44 flow[pre[u]][u]+=a[en]; 45 flow[u][pre[u]]-=a[en]; 46 } 47 maxflow+=a[en]; 48 } 49 return maxflow; 50 } 51 52 int main() 53 { 54 while(scanf("%d%d%d%d",&n,&np,&nc,&m) != EOF) 55 { 56 int u,v,c; 57 memset(cap,0,sizeof(cap)); 58 for(int i=0;i<m;i++) 59 { 60 scanf(" (%d,%d)%d",&u,&v,&c); 61 cap[u+1][v+1]+=c; 62 } 63 for(int i=0;i<np;i++) 64 { 65 scanf(" (%d)%d",&v,&c); 66 cap[0][v+1]+=c; 67 } 68 for(int i=0;i<nc;i++) 69 { 70 scanf(" (%d)%d",&u,&c); 71 cap[u+1][n+1]+=c; 72 } 73 st=0,en=n+1; 74 printf("%d\n",EK()); 75 } 76 return 0; 77 }
dinic算法模版:
10945264 | xinghan0219 | 1459 | Accepted | 720K | 422MS | G++ | 1669B | 2012-10-23 10:11:55 |
View Code
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 6 using namespace std; 7 8 #define MAXN 105 9 #define inf 0x7ffffff 10 #define Min(x,y) (x>y?y:x) 11 int cap[MAXN][MAXN];//记录图的邻接矩阵 12 int dis[MAXN];//记录图中各点的层次 13 int n,m;//点,边 14 int st,en;//源点,汇点 15 16 bool bfs() 17 { 18 queue<int>q; 19 while(!q.empty()) q.pop(); 20 memset(dis,-1,sizeof(dis)); 21 dis[st]=0;//如果处理不慎就很容易死循环 22 q.push(st); 23 while(!q.empty()) 24 { 25 int u=q.front();q.pop(); 26 for(int v=0;v<=n+1;v++)//注意此处是所有顶点(0,n+1是超级源点,汇点) 27 if(dis[v]==-1 && cap[u][v])//此处应是cap[v][i]!=0,因为dfs是可能会走错,这样可以对其进行修正。 28 { 29 dis[v]=dis[u]+1; 30 q.push(v); 31 } 32 } 33 return dis[en]!=-1;//汇点的层次不等于-1说明找到 34 } 35 36 int dfs(int u,int cur_flow) 37 { 38 int dt=cur_flow; 39 if(u==en) return cur_flow; 40 for(int v=0;v<=n+1;v++)//注意此处是所有顶点 41 { 42 if(cap[u][v]>0 && dis[u]+1==dis[v]) 43 { 44 int flow=dfs(v,Min(dt,cap[u][v])); 45 cap[u][v]-=flow; 46 cap[v][u]+=flow; 47 dt-=flow; 48 } 49 } 50 return cur_flow-dt; 51 } 52 int dinic() 53 { 54 int cur_flow,ans=0; 55 while(bfs())//一次bfs可以找到几条增广路 56 { 57 while(cur_flow=dfs(st,inf)) 58 ans+=cur_flow; 59 } 60 return ans; 61 } 62 63 int main() 64 { 65 int np,nc; 66 while(scanf("%d%d%d%d",&n,&np,&nc,&m) != EOF) 67 { 68 int u,v,c; 69 memset(cap,0,sizeof(cap)); 70 for(int i=0;i<m;i++) 71 { 72 scanf(" (%d,%d)%d",&u,&v,&c); 73 cap[u+1][v+1]+=c; 74 } 75 for(int i=0;i<np;i++) 76 { 77 scanf(" (%d)%d",&v,&c); 78 cap[0][v+1]+=c; 79 } 80 for(int i=0;i<nc;i++) 81 { 82 scanf(" (%d)%d",&u,&c); 83 cap[u+1][n+1]+=c; 84 } 85 st=0,en=n+1; 86 printf("%d\n",dinic()); 87 } 88 return 0; 89 }