poj1273Drainage Ditches

简介:
复制代码
 1 #include<iostream>
 2 /*
 3     题意:就是寻找从源点到汇点的最大流!
 4           要注意的是每两个点的流量可能有多个,也就是说有重边,所以要把两个点的所有的流量都加起来
 5           就是这两个点之间的流量了!
 6           
 7     思路:建图之后直接套用最大流算法(EK, 或者是Dinic算法) 图解Dinic算法流程!
8 */ 9 #include<queue> 10 #include<cstring> 11 #include<cstdio> 12 #include<algorithm> 13 #define INF 0x3f3f3f3f3f3f3f3f 14 #define N 205 15 using namespace std; 16 typedef long long LL; 17 LL cap[N][N]; 18 19 int m, n; 20 LL maxFlow; 21 int d[N]; 22 queue<int>q; 23 24 bool bfs(){ 25 q.push(1); 26 memset(d, 0, sizeof(d)); 27 d[1]=1; 28 while(!q.empty()){ 29 int u=q.front(); 30 q.pop(); 31 for(int v=1; v<=n; ++v) 32 if(!d[v] && cap[u][v]>0){ 33 d[v]=d[u]+1; 34 q.push(v); 35 } 36 } 37 if(!d[n]) return false; 38 return true; 39 } 40 41 LL dfs(int u, LL flow){ 42 if(u==n) return flow; 43 for(int v=1; v<=n; ++v) 44 if(d[v]==d[u]+1 && cap[u][v]>0){ 45 LL a=dfs(v, min(flow, cap[u][v])); 46 if(a==0) continue;//如果a==0 说明没有找到从起点到汇点的增广路, 然后换其他路接着寻找! 47 cap[u][v]-=a; 48 cap[v][u]+=a; 49 return a; 50 } 51 return 0; 52 } 53 54 void Dinic(){ 55 LL flow; 56 while(bfs()){//利用bfs构造好层次图,这样dfs在寻找阻塞流的时候,就不会盲目的寻找了! 57 while(flow=dfs(1, INF)) maxFlow+=flow;//利用构造好的层次图不断的寻找阻塞流! 58 } 59 } 60 61 int main(){ 62 while(scanf("%d%d", &m, &n)!=EOF){ 63 memset(cap, 0, sizeof(cap)); 64 while(m--){ 65 int u, v; 66 LL w; 67 scanf("%d%d%lld", &u, &v, &w); 68 cap[u][v]+=w; 69 } 70 maxFlow=0; 71 Dinic(); 72 printf("%lld\n", maxFlow); 73 } 74 return 0; 75 }

复制代码
 1 //EK算法同样搞定
 2 #include<iostream>
 3 #include<queue>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<algorithm>
 7 #define INF 0x3f3f3f3f
 8 using namespace std;
 9 typedef __int64 LL;
10 LL cap[205][205];
11 int pre[205];
12 LL a[205];
13 int m, n;
14 queue<int>q;
15 LL maxFlow;
16 bool spfa(){
17    while(!q.empty()) q.pop();
18    memset(a, 0, sizeof(a));
19    q.push(1);
20    a[1]=INF;
21    while(!q.empty()){
22       int u=q.front();
23       q.pop();
24       for(int v=1; v<=n; ++v)                  
25          if(!a[v] && cap[u][v]>0){
26             pre[v]=u;
27             a[v]=min(a[u], cap[u][v]);
28             q.push(v);         
29          }
30       if(a[n]) break;
31    } 
32    if(!a[n]) return false;
33    return true;
34 }
35 
36 void EK(){
37     maxFlow=0;
38     while(spfa()){
39        int u=n;
40        maxFlow+=a[n];
41        while(u!=1){
42            cap[pre[u]][u]-=a[n];
43            cap[u][pre[u]]+=a[n];            
44            u=pre[u];
45        }         
46     }     
47 }
48 int main(){
49    while(scanf("%d%d", &m, &n)!=EOF){
50          memset(cap, 0, sizeof(cap));
51          while(m--){
52             int u, v;
53             LL w;
54             scanf("%d%d%I64d", &u, &v, &w);
55             cap[u][v]+=w;  
56          }
57          EK();
58          printf("%I64d\n", maxFlow);
59    }
60    return 0;    
61 }
复制代码

 










本文转自 小眼儿 博客园博客,原文链接:http://www.cnblogs.com/hujunzheng/p/3940482.html,如需转载请自行联系原作者
目录
相关文章
poj 3298 数状数组
题目大意是一条大街上住着n个乒乓球爱好者,他们的水平高低用一个数值表示,他们经常举办比赛,比赛要三个人,一人当裁判。对裁判是有一定要求的,裁判的水平必须介于两选手之间且必须住他们中间,计算可以举办多少场比赛
41 0
|
C语言
poj 2503 查字典
Description You have just moved from Waterloo to a big city. The people here speak an incomprehensible dialect of a foreign language.
866 0
poj 1455
Description n participants of > sit around the table. Each minute one pair of neighbors can change their places.
618 0
|
测试技术
poj-1218 THE DRUNK JAILER 喝醉的狱卒
自己去看看原题; 题目大意: 就是一个狱卒喝醉了,他第一趟吧所有的监狱都带开,第二趟把能把二整除的监狱关闭,第三趟操作能把三整除的监狱; 求最后能逃跑的罪犯数 输入第一个数是代表 测试数据组数 每个数据代表狱卒来回的次数 当作开关问题即可 #include using names...
1008 0
|
人工智能 BI
poj-3185-开关问题
描述   牛一行20他们喝的水碗。碗可以那么(面向正确的为清凉水)或颠倒的(一个位置而没有水)。他们希望所有20个水碗那么,因此用宽鼻子翻碗。   嘴太宽,他们不仅翻转一碗还碗的碗两侧(总共三个或三个——在两端的情况下碗——两碗)。
811 0
|
算法 数据建模 机器学习/深度学习
poj1273Drainage Ditches
1 #include 2 /* 3 题意:就是寻找从源点到汇点的最大流! 4 要注意的是每两个点的流量可能有多个,也就是说有重边,所以要把两个点的所有的流量都加起来 5 就是这两个点之间的流量了! 6 ...
851 0