【板子】网络流

最大流:

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

dinic:

 1 //dinic
 2 
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <string.h>
 6 #include <cstdio>
 7 #include <queue>
 8 using namespace std;
 9 const int inf = 0x3f3f3f3f;
10 const int maxn = 205;
11 const int maxm = maxn*maxn;
12 struct node{int w; int v, next;} edge[maxm];
13 int pre[maxn], rec[maxn], head[maxn], block[maxn];
14 int dis[maxn];
15 int n, m, no;
16 int S, T;
17 queue<int> q;
18 inline void init(){
19     no = 0;
20     memset(head, -1, sizeof head);
21 }
22 inline void add(int u, int v, int w){
23     edge[no].v = v; edge[no].w = w;
24     edge[no].next = head[u]; head[u] = no++;
25     edge[no].v = u; edge[no].w = 0;
26     edge[no].next = head[v]; head[v] = no++;
27 }
28 void reset(int S, int T){
29     memset(dis, 0x3f, sizeof dis);
30     memset(block, 0, sizeof block);
31     q.push(S); dis[S] = 0;
32     while(!q.empty()){
33         int top = q.front(); q.pop();
34         for(int k = head[top]; k != -1; k = edge[k].next)
35         if(dis[edge[k].v] == inf && edge[k].w)
36             dis[edge[k].v] = dis[top]+1, q.push(edge[k].v);
37     }
38 }
39 int dinic(int S, int T){
40     int ans = 0, flow = inf;
41     int top = S;
42     reset(S, T); pre[S] = S;
43     while(dis[T] != inf){
44         int k, tmp;
45         for(k = head[top]; k != -1; k = edge[k].next){
46             if(edge[k].w && dis[edge[k].v]==dis[top]+1 && 
47             !block[edge[k].v]) break;
48         }
49         if(k != -1){
50             tmp = edge[k].v;
51             flow = min(flow, edge[k].w);
52             pre[tmp] = top, rec[tmp] = k;
53             top = tmp;
54             if(top == T){
55                 ans += flow; tmp = -1;
56                 for(; top != S; top = pre[top]){
57                     edge[rec[top]].w -= flow;
58                     edge[rec[top]^1].w += flow;
59                     if(!edge[rec[top]].w) tmp = top;
60                 }
61                 flow = inf;
62                 if(tmp != -1){
63                     top = pre[tmp];
64                     for(; top != S; top = pre[top])
65                     flow = min(flow, edge[rec[top]].w);
66                     top = pre[tmp];
67                 }
68             }
69         }
70         else{
71             block[top] = 1;
72             top = pre[top];
73             if(block[S]) reset(S, T);
74         }
75     }
76     return ans;
77 }
78 void mapping(){
79     int u, v, w;
80     for(int i = 1; i <= m; ++i){
81         scanf("%d %d %d", &u, &v, &w);
82         add(u, v, w);
83     }
84 }
85 int main(){
86     while(~scanf("%d %d", &m, &n)){
87         S = 1, T = n;
88         init();
89         mapping();
90         printf("%d\n", dinic(S, T));
91     }
92     return 0;
93 }

 

sap:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<cstdlib>
  6 #include<string>
  7 #include<queue>
  8 #include<algorithm>
  9 using namespace std;
 10  
 11 const int N=100010;
 12 const int M=400010;
 13 const int inf=0xfffffff;
 14  
 15 int n,m,cnt;
 16  
 17 struct Edge{
 18     int v , cap , next;
 19 } edge[M];
 20  
 21 int head[N],pre[N],d[N],numd[N];//分别为链表的头指针,每个点的前驱,每个点的d值,以及标号为d[i] 的点的个数
 22 int cur_edge[N];//从每个点出发满足d[i] = d[j] + 1的边的地址 , 插入边时的计数,源点与汇点
 23  
 24 void addedge(int u,int v,int c){
 25  
 26     edge[cnt].v = v;
 27     edge[cnt].cap = c;
 28     edge[cnt].next = head[u];
 29     head[u] = cnt++;
 30  
 31     edge[cnt].v = u;
 32     edge[cnt].cap = 0;
 33     edge[cnt].next = head[v];
 34     head[v] = cnt++;
 35 }
 36  
 37 void bfs(int s){    //先用广度优先算出每个点的d值
 38     memset(numd,0,sizeof(numd));
 39     for(int i=1; i<=n; i++)
 40         numd[ d[i] = n ]++;
 41     d[s] = 0;
 42     numd[n]--;
 43     numd[0]++;
 44     queue<int> Q;
 45     Q.push(s);
 46  
 47     while(!Q.empty()){
 48         int v=Q.front();
 49         Q.pop();
 50  
 51         int i=head[v];
 52         while(i != -1){
 53             int u=edge[i].v;
 54  
 55             if(d[u]<n){
 56                 i=edge[i].next;
 57                 continue ;
 58             }
 59  
 60             d[u]=d[v]+1;
 61             numd[n]--;
 62             numd[d[u]]++;
 63             Q.push(u);
 64             i=edge[i].next;
 65         }
 66     }
 67 }
 68 
 69 int SAP(int s,int t){
 70     for(int i = 1; i <= n; i++)
 71         cur_edge[i] = head[i];   //当前满足d[i] = d[j] + 1的边的为第一条边
 72     int max_flow=0;
 73     bfs(t);
 74     int u = s ;//从源点搜一条到汇点的增广路
 75     while(d[s]<n){//就算所有的点连成一条线源点的d值也是最多是n-1
 76         if(u == t){//如果找到一条增广路径
 77             int cur_flow = inf,neck;//找到那条瓶颈边
 78             for(int from = s; from != t; from = edge[cur_edge[from]].v){
 79                 if(cur_flow > edge[cur_edge[from]].cap){
 80                     neck = from;
 81                     cur_flow = edge[cur_edge[from]].cap;
 82                 }
 83             }
 84  
 85             for(int from = s; from != t; from = edge[cur_edge[from]].v){    //修改增广路上的边的容量
 86                 int tmp = cur_edge[from];
 87                 edge[tmp].cap -= cur_flow;
 88                 edge[tmp^1].cap += cur_flow;
 89             }
 90             max_flow += cur_flow;//累加计算最大流
 91             u = neck;//下一次搜索直接从瓶颈边的前一个节点搜起
 92         }
 93  
 94         int i;
 95         for(i = cur_edge[u]; i != -1; i = edge[i].next) //从当前点开始找一条允许弧
 96             if(edge[i].cap && d[u] == d[edge[i].v]+1)//如果找到跳出循环
 97                 break;
 98  
 99         if(i!=-1){//找到一条允许弧
100             cur_edge[u] = i;//从点u出发的允许弧的地址
101             pre[edge[i].v] = u;//允许弧上下一个点的前驱为u
102             u = edge[i].v;//u变成下一个点继续搜直到搜出一条增广路
103         }
104         else{//如果没有搜到允许弧
105             numd[d[u]]--; //d[u]将被修改所以numd[d[u]]减一
106             if(!numd[d[u]]) break;  //如果没有点的d值为d[u]则不可能再搜到增广路结束搜索
107             cur_edge[u] = head[u];  //当前点的允许弧为第一条边
108             int tmp = n;
109             for(int j = head[u]; j != -1; j = edge[j].next) //搜与u相连的点中d值最小的
110                 if(edge[j].cap && tmp > d[edge[j].v])
111                     tmp = d[edge[j].v];
112  
113             d[u] = tmp+1; //修改d[u]
114             numd[d[u]]++;
115             if(u != s)
116                 u = pre[u];//从u的前驱搜,因为从u没有搜到允许弧
117         }
118     }
119     return max_flow;
120 }
121 inline void pre_init(){ 
122     cnt = 0;
123     memset(head, -1, sizeof head);  
124 } 
125 
126 void mapping(){
127     int u, v, w;
128     for(int i = 1; i <= m; ++i){  
129         scanf("%d %d %d", &u, &v, &w); 
130         addedge(u, v, w);  
131     }
132 }
133 
134 int main(){
135     while(~scanf("%d%d",&m,&n)){
136         pre_init();
137         mapping();
138         int s,t;
139         s = 1;t = n;
140         int ans = SAP(s,t);
141         printf("%d\n",ans);
142     }
143     return 0;
144 }

 

posted @ 2018-10-07 19:48  甜酒果。  阅读(214)  评论(0编辑  收藏  举报