Drainage Ditches(Dinic最大流)

http://poj.org/problem?id=1273

用Dinic求最大流的模板题,注意会有重边。

邻接矩阵建图

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<queue>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn = 510;
 7 const int INF = 0x3f3f3f3f;
 8 int flow[maxn][maxn];//残量
 9 int m,n;
10 int dis[maxn];
11 int bfs()//按层数“建”图,就是对每层的点用dis标记它到源点的层数
12 {
13     queue<int>que;
14     memset(dis,-1,sizeof(dis));
15     while(!que.empty())
16         que.pop();
17     dis[1] = 0;
18     que.push(1);
19 
20     while(!que.empty())
21     {
22         int u = que.front();
23         que.pop();
24 
25         for(int i = 1; i <= n; i++)
26         {
27             if(flow[u][i] > 0 && dis[i] < 0)
28             {
29                 dis[i] = dis[u]+1;
30                 que.push(i);
31             }
32         }
33     }
34 
35     if(dis[n] > 0)
36         return 1;
37     else return 0;
38 }
39 //dfs寻找路径上的最小流量
40 int dfs(int s, int mf)
41 {
42     int a;
43     if(s == n)
44         return mf;
45     for(int i = 1; i <= n; i++)
46     {
47         if(dis[i] == dis[s] + 1 && flow[s][i] > 0 && (a = dfs(i,min(mf,flow[s][i]))))
48         {
49             flow[s][i] -= a;
50             flow[i][s] += a;
51             return a;
52         }
53     }
54     return 0;
55 }
56 
57 int main()
58 {
59     while(~scanf("%d %d",&m,&n))
60     {
61         int u,v,w;
62         memset(flow,0,sizeof(flow));
63         for(int i = 0; i < m; i++)
64         {
65             scanf("%d %d %d",&u,&v,&w);
66             flow[u][v] += w;
67         }
68         int ans = 0,res;
69         while(bfs())//bfs寻找源点到汇点是否有路
70         {
71             res = dfs(1,INF);
72             if(res > 0)
73                 ans += res;
74         }
75         printf("%d\n",ans);
76     }
77     return 0;
78 
79 }
View Code

邻接表建图

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<queue>
  4 #include<algorithm>
  5 using namespace std;
  6 const int maxn = 510;
  7 const int INF = 0x3f3f3f3f;
  8 int m,n,cnt;
  9 struct node
 10 {
 11     int u,v,w;
 12     int next;
 13 }edge[maxn];
 14 int p[maxn];
 15 int dis[maxn];
 16 void add(int u, int v, int w)
 17 {
 18 
 19     edge[cnt].u = u;
 20     edge[cnt].v = v;
 21     edge[cnt].w = w;
 22     edge[cnt].next = p[u];
 23     p[u] = cnt++;
 24 
 25     edge[cnt].u = v;
 26     edge[cnt].v = u;
 27     edge[cnt].w = 0;
 28     edge[cnt].next = p[v];
 29     p[v] = cnt++;
 30 }
 31 
 32 int bfs()
 33 {
 34     queue<int> que;
 35     while(!que.empty())
 36         que.pop();
 37     memset(dis,-1,sizeof(dis));
 38     dis[1] = 0;
 39     que.push(1);
 40 
 41     while(!que.empty())
 42     {
 43         int u = que.front();
 44         que.pop();
 45 
 46         for(int i = p[u]; i != -1; i = edge[i].next)
 47         {
 48             if(edge[i].w > 0 && dis[ edge[i].v ] < 0)
 49             {
 50                 dis[ edge[i].v ] = dis[u] + 1;
 51                 que.push(edge[i].v);
 52             }
 53         }
 54     }
 55     if(dis[n] > 0)
 56         return 1;
 57     else return 0;
 58 }
 59 
 60 int dfs(int s, int mf)
 61 {
 62     if(s == n)
 63         return mf;
 64     int a;
 65     int tf = 0;
 66     for(int i = p[s]; i != -1; i = edge[i].next)
 67     {
 68         int v = edge[i].v;
 69         int w = edge[i].w;
 70         if(dis[v] == dis[s] + 1 && w > 0 && (a = dfs(v,min(mf,w))))
 71         {
 72             edge[i].w -= a;
 73             edge[i^1].w += a;
 74             return a;
 75         }
 76     }
 77     if(!tf)//若找不到小流,从这个点到不了汇点,把这个点从分层图删去
 78         dis[s] = -1;
 79     return tf;
 80 }
 81 
 82 int main()
 83 {
 84     while(~scanf("%d %d",&m,&n))
 85     {
 86         int u,v,w;
 87         cnt = 0;
 88         memset(p,-1,sizeof(p));
 89         for(int i = 0; i < m; i++)
 90         {
 91             scanf("%d %d %d",&u,&v,&w);
 92             add(u,v,w);
 93         }
 94         int ans = 0;
 95         int res;
 96         while(bfs())
 97         {
 98             res = dfs(1,INF);
 99             if(res > 0)
100                 ans += res;
101         }
102         printf("%d\n",ans);
103     }
104 
105     return 0;
106 }
View Code

 

转载于:https://www.cnblogs.com/LK1994/p/3462803.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值