最大流介绍太多 这里不说了
1 //hdu3549为例 2 3 4 (1)初始化网络 5 (2)网络中BFS找,若汇点值为改变表明没有增广路 6 7 8 9 10 /*EK算法*/ 11 #include<stdio.h> 12 #include<queue> 13 #include<string.h> 14 using namespace std; 15 #define INF 999999999 16 int c[20][23],f[23][23],pre[23]; 17 int n,m; 18 int min(int x,int y) 19 { 20 return x<y?x:y; 21 } 22 int maxflow(int s,int e) 23 { 24 int i,j; 25 int res[23]; //记录当前能增广多少 26 queue<int>q; 27 int ans=0; 28 while(1) 29 { 30 memset(res,0,sizeof(res)); 31 res[s]=INF; 32 pre[s]=-1; //保留路径 33 q.push(s); 34 while(!q.empty())//BFS 每次都去找增广路 直到没有增光路为止 35 { 36 int u=q.front(); 37 q.pop(); 38 for(i=1;i<=e;i++) 39 { 40 if(!res[i]&&f[u][i]<c[u][i]) //如果当前点之前未访问并且是可行的 41 { 42 q.push(i); 43 pre[i]=u; 44 res[i]=min(res[u],c[u][i]-f[u][i]); //记录可以增广的值 45 } 46 } 47 } 48 if(res[e]==0) //没有路了 49 { 50 break; 51 } 52 j=e; 53 while(pre[j]!=-1)//根据路径改变流量 54 { 55 f[pre[j]][j]+=res[e]; 56 f[j][pre[j]]-=res[e]; 57 j=pre[j]; 58 } 59 ans+=res[e]; 60 } 61 return ans; 62 } 63 int main() 64 { 65 int t,i,j; 66 scanf("%d",&t); 67 int ff=0; 68 while(t--) 69 { 70 scanf("%d%d",&n,&m); 71 memset(c,0,sizeof(c)); 72 memset(f,0,sizeof(f)); 73 for(i=0;i<m;i++) 74 { 75 int x,y,z; 76 scanf("%d%d%d",&x,&y,&z); 77 c[x][y]+=z; 78 } 79 int ans=maxflow(1,n); 80 printf("Case %d: %d\n",++ff,ans); 81 } 82 }
1 /*dinic算法*/ 2 #include<stdio.h> 3 #include<string.h> 4 #include<queue> 5 using namespace std; 6 #define INF 99999999 7 int n,m; 8 int dis[20],c[20][20];//dis[]用来表示层次关系 9 int min(int x,int y) 10 { 11 return x<y?x:y; 12 } 13 int BFS(int s,int e) 14 { 15 int i,j; 16 queue<int>q; 17 memset(dis,-1,sizeof(dis)); 18 dis[s]=0; 19 q.push(s); 20 while(!q.empty()) 21 { 22 int u=q.front(); 23 q.pop(); 24 for(i=1;i<=e;i++) 25 { 26 if(c[u][i]>0&&dis[i]<0) 27 { 28 q.push(i); 29 dis[i]=dis[u]+1; 30 } 31 } 32 } 33 if(dis[e]>0) 34 return 1; 35 return 0; 36 } 37 int dfs(int x,int low) 38 { 39 int i,j; 40 int a=0; 41 if(x==n) 42 return low; 43 for(i=1;i<=n;i++) 44 { 45 if(c[x][i]&&dis[i]==dis[x]+1)//如果该路可通并且有层次关系 46 { 47 a=dfs(i,min(low,c[x][i]));//能否到汇点 48 if(a) 49 { 50 c[x][i]-=a;//修改正向流量 51 c[i][x]+=a;//改变反向的 52 return a; 53 } 54 } 55 } 56 return 0; 57 } 58 int main() 59 { 60 int i,j; 61 int t,ff; 62 scanf("%d",&t); 63 ff=0; 64 while(t--) 65 { 66 scanf("%d%d",&n,&m); 67 memset(c,0,sizeof(c)); 68 for(i=0;i<m;i++) 69 { 70 int x,y,z; 71 scanf("%d%d%d",&x,&y,&z); 72 c[x][y]+=z; 73 } 74 int ans=0; 75 int s; 76 while(BFS(1,n))//构建层次网络 77 { 78 while(s=dfs(1,INF))//在层次图中不断寻找增广路 79 ans+=s; 80 } 81 printf("Case %d: %d\n",++ff,ans); 82 } 83 }
1 //poj1273 dinic算法 2 /*看着大牛的模版敲出来*/ 3 4 #include<stdio.h> 5 #include<string.h> 6 #include<queue> 7 #define INF 99999999 8 #define min(x,y) (x<y?x:y) 9 using namespace std; 10 int c[203][203],f[203][203]; 11 int dis[203]; 12 int n,m; 13 int BFS(int s,int e) 14 { 15 queue<int>q; 16 int i,j; 17 18 memset(dis,-1,sizeof(dis)); 19 dis[s]=0; 20 q.push(s); 21 while(!q.empty()) 22 { 23 int u=q.front(); 24 q.pop(); 25 for(i=1;i<=e;i++) 26 { 27 if(dis[i]<0&&c[u][i]) 28 { 29 dis[i]=dis[u]+1;//层次关系 30 q.push(i); 31 } 32 } 33 } 34 if(dis[e]<=0)//汇点没改变 表明无法构建层次图 35 return 0; 36 return 1; 37 38 } 39 int dfs(int x,int low)//low表示还能改变多少 40 { 41 int i,j; 42 int a=0; 43 if(x==m) 44 return low; 45 for(i=1;i<=m;i++) 46 { 47 if(c[x][i]>0&&dis[i]==dis[x]+1)//如果有层次关系并且存在路 48 { 49 a=dfs(i,min(low,c[x][i]));//dfs看能否到汇点 50 if(a) 51 { 52 c[x][i]-=a; 53 c[i][x]+=a; 54 return a; 55 } 56 } 57 } 58 return 0; 59 } 60 int main() 61 { 62 int i,j; 63 while(scanf("%d%d",&n,&m)!=EOF) 64 { 65 memset(c,0,sizeof(c)); 66 memset(f,0,sizeof(f)); 67 for(i=0;i<n;i++) 68 { 69 int x,y,z; 70 scanf("%d%d%d",&x,&y,&z); 71 c[x][y]+=z; 72 } 73 int ans=0; 74 int s; 75 while(BFS(1,m))//BFS构建层次图 如果不能构建出层次图表明结束 76 { 77 while(s=dfs(1,INF))//一次BFS要不停地找增广路,直到找不到为止 78 ans+=s; 79 } 80 printf("%d\n",ans); 81 } 82 }
1 //poj2112 这道题让我知道了遇到最大最小的时候可以用二分法来解决 2 #include<stdio.h> 3 #include<string.h> 4 #include<queue> 5 #define MAXN 1003 6 #define INF 99999999 7 using namespace std; 8 int res[MAXN]; 9 int map[MAXN][MAXN],dis[MAXN][MAXN]; 10 int n,k,c,m; 11 int min(int x,int y) 12 { 13 return x<y?x:y; 14 } 15 void buildmap(int max) 16 { 17 memset(map,0,sizeof(map));//这步开始没写 搞了2小时。。。 18 int i,j; 19 //将牛与源点相连容量为1,将机器与汇点相连容量为m 20 for(i=k+1;i<=n;i++)//源点到牛的距离为1 21 map[0][i]=1; 22 for(i=1;i<=k;i++)//挤奶点的距离到会点的距离为m 23 map[i][n+1]=m; 24 for(i=k+1;i<=n;i++)////如果奶牛到挤奶点的距离小于枚举距离(即可行) 25 for(j=1;j<=k;j++)// 26 { 27 if(dis[i][j]<=max)//max为二分枚举的最长路的最小值 28 map[i][j]=1; 29 } 30 } 31 int BFS() 32 { 33 int i,j; 34 memset(res,-1,sizeof(res)); 35 res[0]=0; 36 queue<int>q; 37 q.push(0); 38 while(!q.empty()) 39 { 40 int u=q.front(); 41 q.pop(); 42 for(i=0;i<=n+1;i++) 43 { 44 if(res[i]<0&&map[u][i]>0) 45 { 46 res[i]=res[u]+1; 47 q.push(i); 48 } 49 } 50 } 51 if(res[n+1]>0) 52 return 1; 53 return 0; 54 } 55 int DFS(int x,int low) 56 { 57 int i,j,a; 58 a=0; 59 if(x==n+1) 60 return low; 61 for(i=0;i<=n+1;i++) 62 { 63 if((res[i]==res[x]+1)&&map[x][i]>0) 64 { 65 a=DFS(i,min(low,map[x][i])); 66 if(a) 67 { 68 map[x][i]-=a; 69 map[i][x]+=a; 70 return a; 71 } 72 } 73 } 74 return 0; 75 } 76 int main() 77 { 78 int i,j; 79 while(scanf("%d%d%d",&k,&c,&m)!=EOF) 80 { 81 n=k+c; 82 for(i=1;i<=n;i++) 83 for(j=1;j<=n;j++) 84 { 85 scanf("%d",&dis[i][j]); 86 if(!dis[i][j]) 87 dis[i][j]=INF; 88 } 89 //floyd 90 for(i=1;i<=n;i++) 91 for(j=1;j<=n;j++) 92 for(int h=1;h<=n;h++) 93 { 94 dis[j][h]=min(dis[j][h],dis[j][i]+dis[i][h]); 95 } 96 //最大最小用二分法 97 int l,r,mid; 98 l=0;r=10000;//这里指floyd算法距离最大的上限 由于知道这个麻烦 直接写个大的 99 int ans,t; 100 while(l<r) 101 { 102 ans=0; 103 mid=(l+r)/2; 104 buildmap(mid); 105 //dinic算法 106 while(BFS()) 107 { 108 while(t=DFS(0,INF)) 109 ans+=t; 110 } 111 if(ans>=c) 112 r=mid; 113 else l=mid+1; 114 } 115 printf("%d\n",r); 116 } 117 }
时间: 2024-10-01 06:23:34