zoukankan      html  css  js  c++  java
  • [POJ1273]Drainage Ditches 网络流(最大流)

    题目链接:http://poj.org/problem?id=1273

      网络流裸题,注意有重边。重边的处理方法很简单,就是将对应的c叠加到对应边上。注意初始化为0。

      我用的是最朴素的FF方法,即找增广路。之前用dfs找增广路WA了,应该是碰到了随机找一条增光路这种方法碰到了killer case。给出WA代码(初学用喜闻乐见链式前向星建图,比较繁琐。不过好在最终还是WA掉了)。

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <iomanip>
     4 #include <cstring>
     5 #include <climits>
     6 #include <complex>
     7 #include <fstream>
     8 #include <cassert>
     9 #include <cstdio>
    10 #include <bitset>
    11 #include <vector>
    12 #include <deque>
    13 #include <queue>
    14 #include <stack>
    15 #include <ctime>
    16 #include <set>
    17 #include <map>
    18 #include <cmath>
    19 
    20 using namespace std;
    21 
    22 typedef struct Edge {
    23     int v;
    24     int c;
    25     int next;
    26     Edge() { next = -1; }
    27 }Edge;
    28 
    29 const int maxn = 222;
    30 int n, m, s, t;
    31 int head[maxn];
    32 int vis[maxn];
    33 int cnt = 0;
    34 Edge edge[maxn<<1];
    35 
    36 void init() {
    37     memset(head, -1, sizeof(head));
    38     memset(vis, 0, sizeof(vis));
    39     cnt = 0;
    40 }
    41 
    42 void adde(int u, int v, int c) {
    43     edge[cnt].v = v; edge[cnt].next = head[u];
    44     edge[cnt].c = c; head[u] = cnt++;
    45     edge[cnt].v = v; edge[cnt].next = head[u];
    46     edge[cnt].c = 0; head[v] = cnt++;
    47 }
    48 
    49 int dfs(int v, int f) {
    50     if(v == t) return f;
    51     vis[v] = 1;
    52     for(int i = head[v]; ~i; i = edge[i].next) {
    53         if(!vis[edge[i].v] && edge[i].c > 0) {
    54             int d = dfs(edge[i].v, min(f, edge[i].c));
    55             if(d > 0) {
    56                 edge[i].c -= d;
    57                 edge[i+1].c += d;
    58                 return d;
    59             }
    60         }
    61     }
    62     return 0;
    63 }
    64 
    65 int max_flow() {
    66     int flow = 0;
    67     while(1) {
    68         memset(vis, 0, sizeof(vis));
    69         int tf = dfs(s, 2147483647);
    70         if(tf == 0) return flow;
    71         flow += tf;
    72     }
    73     return flow;
    74 }
    75 
    76 int main() {
    77     // freopen("in", "r", stdin);
    78     int u, v, c;
    79     while(~scanf("%d %d", &m, &n)) {
    80         init();
    81         for(int i = 0; i < m; i++) {
    82             scanf("%d %d %d", &u, &v, &c);
    83             adde(u, v, c);
    84         }
    85         s = 1;
    86         t = n;
    87         printf("%d
    ", max_flow());
    88     }
    89     return 0;
    90 }

      随后索性全部删掉一切从简,改用最简单的邻接矩阵。利用BFS,第一次接触到汇点的那条路径一定是最短的(因为BFS是层进的)。找到了这条路并且记录下来即可。

    接着,从源向外发出一个流(一定要足够大),按照之前BFS到的最短增广路流向汇点,根据短板效应找到流量,更新到最大流量上之后再更新残余网络(直接在原网络上更新即可)。下图可以比较清晰地说明这一点:

    简要证明:

      我们从右图化简它的过程以及路径得到了右图。假设图中的源点可由b流经a到达汇点,而且假设b->a在当前所找到的增广路上,表示为G[b][a]。再假设该路上的流量为k,容量为n,那么当前b->a上的流量应被修改为k,且该路径在残余网络上残余的容量是n-k。而残余网络上,该路径表示为G[a][b]。如左图所示,对这两条路进行了一次合并,那么规定原图上初始流向为正方向,那么当前网络和残余网络上该路上的流量应当是n+(-(n-k))=n-n+k=k。因此只需要对两部分更新流量k就好了。在代码中,b相当于a的前驱点,也就是pre[a]。那么我们更新残余网络上对应的路的时候(也就是更新G[a][pre[a]]),相当于+k,而更新原图(G[pre[a]][a])的时候,相当于-k。

    代码如下:

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <iomanip>
     4 #include <cstring>
     5 #include <climits>
     6 #include <complex>
     7 #include <fstream>
     8 #include <cassert>
     9 #include <cstdio>
    10 #include <bitset>
    11 #include <vector>
    12 #include <deque>
    13 #include <queue>
    14 #include <stack>
    15 #include <ctime>
    16 #include <set>
    17 #include <map>
    18 #include <cmath>
    19 
    20 using namespace std;
    21 
    22 const int inf = 0x7fffff;
    23 const int maxn = 222;
    24 int G[maxn][maxn];
    25 int pre[maxn];
    26 int vis[maxn];
    27 int m, n, s, t;
    28 
    29 void init() {
    30     memset(G, 0, sizeof(G));
    31     memset(pre, 0, sizeof(pre));
    32     memset(vis, 0, sizeof(vis));
    33 }
    34 
    35 bool bfs() {
    36     memset(vis, 0, sizeof(vis));
    37     memset(pre, 0, sizeof(pre));
    38     queue<int> q;
    39     q.push(s);
    40     vis[s] = 1;
    41     while(!q.empty()) {
    42         int v = q.front(); q.pop();
    43         for(int i = 1; i <= n; i++) {
    44             if(G[v][i] > 0 && !vis[i]) {
    45                 q.push(i);
    46                 vis[i] = 1;
    47                 pre[i] = v;
    48                 if(i == n) {
    49                     return 1;
    50                 }
    51             }
    52         }
    53     }
    54     return 0;
    55 }
    56 
    57 int max_flow() {
    58     int flow = 0;
    59     while(1) {
    60         if(!bfs()) return flow;
    61         int v = n;
    62         int k = inf;
    63         while(pre[v]) {
    64             k = min(k, G[pre[v]][v]);
    65             v = pre[v];
    66         }
    67         v = n;
    68         flow += k;
    69         while(pre[v]) {
    70             G[v][pre[v]] += k;
    71             G[pre[v]][v] -= k;
    72             v = pre[v];
    73         }
    74     }
    75     return flow;
    76 }
    77 
    78 int main() {
    79     // freopen("in", "r", stdin);
    80     int u, v, c;
    81     while(~scanf("%d %d", &m, &n)) {
    82         init();
    83         for(int i = 0; i < m; i++) {
    84             scanf("%d %d %d", &u, &v, &c);
    85             G[u][v] += c;
    86         }
    87         s = 1; t = n;
    88         printf("%d
    ", max_flow());
    89     }
    90 }

    dinic板子

      1 /*
      2 ━━━━━┒ギリギリ♂ eye!
      3 ┓┏┓┏┓┃キリキリ♂ mind!
      4 ┛┗┛┗┛┃\○/
      5 ┓┏┓┏┓┃ /
      6 ┛┗┛┗┛┃ノ)
      7 ┓┏┓┏┓┃
      8 ┛┗┛┗┛┃
      9 ┓┏┓┏┓┃
     10 ┛┗┛┗┛┃
     11 ┓┏┓┏┓┃
     12 ┛┗┛┗┛┃
     13 ┓┏┓┏┓┃
     14 ┃┃┃┃┃┃
     15 ┻┻┻┻┻┻
     16 */
     17 #include <algorithm>
     18 #include <iostream>
     19 #include <iomanip>
     20 #include <cstring>
     21 #include <climits>
     22 #include <complex>
     23 #include <fstream>
     24 #include <cassert>
     25 #include <cstdio>
     26 #include <bitset>
     27 #include <vector>
     28 #include <deque>
     29 #include <queue>
     30 #include <stack>
     31 #include <ctime>
     32 #include <set>
     33 #include <map>
     34 #include <cmath>
     35 using namespace std;
     36 #define fr first
     37 #define sc second
     38 #define cl clear
     39 #define BUG puts("here!!!")
     40 #define W(a) while(a--)
     41 #define pb(a) push_back(a)
     42 #define Rint(a) scanf("%d", &a)
     43 #define Rs(a) scanf("%s", a)
     44 #define Cin(a) cin >> a
     45 #define FRead() freopen("in", "r", stdin)
     46 #define FWrite() freopen("out", "w", stdout)
     47 #define Rep(i, len) for(int i = 0; i < (len); i++)
     48 #define For(i, a, len) for(int i = (a); i < (len); i++)
     49 #define Cls(a) memset((a), 0, sizeof(a))
     50 #define Clr(a, x) memset((a), (x), sizeof(a))
     51 #define Full(a) memset((a), 0x7f7f7f, sizeof(a))
     52 #define lrt rt << 1
     53 #define rrt rt << 1 | 1
     54 #define pi 3.14159265359
     55 #define RT return
     56 #define lowbit(x) x & (-x)
     57 #define onecnt(x) __builtin_popcount(x)
     58 typedef long long LL;
     59 typedef long double LD;
     60 typedef unsigned long long ULL;
     61 typedef pair<int, int> pii;
     62 typedef pair<string, int> psi;
     63 typedef pair<LL, LL> pll;
     64 typedef map<string, int> msi;
     65 typedef vector<int> vi;
     66 typedef vector<LL> vl;
     67 typedef vector<vl> vvl;
     68 typedef vector<bool> vb;
     69 
     70 typedef struct Edge {
     71     int u, v, c, next;
     72 }Edge;
     73 
     74 const int inf = 0x7f7f7f7f;
     75 const int maxn = 220;
     76 
     77 int cnt, head[maxn];
     78 int cur[maxn], dd[maxn];
     79 Edge edge[maxn*maxn*2];
     80 int N, S, T;
     81 
     82 void init() {
     83     memset(head, -1, sizeof(head));
     84     for(int i = 0; i < maxn; i++) edge[i].next = -1;
     85 }
     86 
     87 void adde(int u, int v, int c, int c1) {
     88     edge[cnt].u = u; edge[cnt].v = v; edge[cnt].c = c; 
     89     edge[cnt].next = head[u]; head[u] = cnt++;
     90     edge[cnt].u = v; edge[cnt].v = u; edge[cnt].c = c1; 
     91     edge[cnt].next = head[v]; head[v] = cnt++;
     92 }
     93 
     94 bool bfs(int s, int t, int n) {
     95     queue<int> q;
     96     for(int i = 0; i < n; i++) dd[i] = inf;
     97     dd[s] = 0;
     98     q.push(s);
     99     while(!q.empty()) {
    100         int u = q.front(); q.pop();
    101         for(int i = head[u]; ~i; i = edge[i].next) {
    102             if(dd[edge[i].v] > dd[u] + 1 && edge[i].c > 0) {
    103                 dd[edge[i].v] = dd[u] + 1;
    104                 if(edge[i].v == t) return 1;
    105                 q.push(edge[i].v);
    106             }
    107         }
    108     }
    109     return 0;
    110 }
    111 
    112 int dinic(int s, int t, int n) {
    113     int st[maxn], top;
    114     int u;
    115     int flow = 0;
    116     while(bfs(s, t, n)) {
    117         for(int i = 0; i < n; i++) cur[i] = head[i];
    118         u = s; top = 0;
    119         while(cur[s] != -1) {
    120             if(u == t) {
    121                 int tp = inf;
    122                 for(int i = top - 1; i >= 0; i--) {
    123                     tp = min(tp, edge[st[i]].c);
    124                 }
    125                 flow += tp;
    126                 for(int i = top - 1; i >= 0; i--) {
    127                     edge[st[i]].c -= tp;
    128                     edge[st[i] ^ 1].c += tp;
    129                     if(edge[st[i]].c == 0) top = i;
    130                 }
    131                 u = edge[st[top]].u;
    132             }
    133             else if(cur[u] != -1 && edge[cur[u]].c > 0 && dd[u] + 1 == dd[edge[cur[u]].v]) {
    134                 st[top++] = cur[u];
    135                 u = edge[cur[u]].v;
    136             }
    137             else {
    138                 while(u != s && cur[u] == -1) {
    139                     u = edge[st[--top]].u;
    140                 }
    141                 cur[u] = edge[cur[u]].next;
    142             }
    143         }
    144     }
    145     return flow;
    146 }
    147 
    148 int n, m;
    149 int G[maxn][maxn];
    150 
    151 int main() {
    152     // FRead();
    153     int u, v, w;
    154     while(~Rint(m) && ~Rint(n)) {
    155         Cls(G); S = 0, N = n, T = n - 1; init();
    156         Rep(i, m) {
    157             Rint(u); Rint(v); Rint(w);
    158             G[u-1][v-1] += w;
    159         }
    160         Rep(i, n) {
    161             Rep(j, n) {
    162                 if(G[i][j] != 0) adde(i, j, G[i][j], 0);
    163             }
    164         }
    165         printf("%d
    ", dinic(S, T, N));
    166     }
    167     RT 0;
    168 }
    Dinic
  • 相关阅读:
    请求分页中的内存分配
    Android开发实例总结
    出现java.lang.IllegalArgumentException异常
    请求分页中的内存分配之续
    HTTPCLIENT使用学习
    传输控制层协议TCP概述抄书
    freemarker中空值 null的处理 ?exists ?if_exists ?default(“”)
    Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring 大新博客 推酷 360安全浏览器 7.1
    jade 学习笔记 gulp 自动编译
    @resource和@autowired的区别是什么CSDN论坛CSDN.NET中国最大的IT技术社区 Google Chrome
  • 原文地址:https://www.cnblogs.com/kirai/p/4961653.html
Copyright © 2011-2022 走看看