码迷,mamicode.com
首页 > 其他好文 > 详细

学习了一下网络流 感觉好难 只会一点最大流 先放放

时间:2015-05-18 22:54:01      阅读:217      评论:0      收藏:0      [点我收藏+]

标签:

最大流介绍太多 这里不说了

 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 }

 

学习了一下网络流 感觉好难 只会一点最大流 先放放

标签:

原文地址:http://www.cnblogs.com/sweat123/p/4513097.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!