关于网络流的二三事(一)

写了一万篇博客,懒得完善,就先不发了。。。

反正在自娱自乐没人看~~

发一篇网络流吧。

今天终于把Ford-Fulkerson升级成了dinic,省选网络流终于不用输出样例了(颓

先看看定义吧。。。

 

 这是百度百科的说法,完全没用。

换个通俗点的解释吧。

初中物理电学还记得吧(膜参加省选的小学生)

现在电路上实现分流,你可以关闭导线或者调整电阻,使分流后到达用电器的电流最大(差不多,别较真了)

洛谷模板题

直接上dinic吧,反正还好理解(当初被无良辅导书坑的只会ek和Ford-Fulkerson的我欲哭无泪)

其实本质就是你在出发点灌水,bfs发现有一条路可以到达终点,然后就在这条路拼命灌水,直到达到最大值放不下而已。

有几点注意:

  • 邻接表建造时留好去路,以便返回。
  • 以层为目标建造一个数组,极大幅度节省时间(核心!!!!)
  • 走不通的时候记得堵上,以免死循环……

直接上程序吧,毕竟第一讲说不了什么,还是理解第一啊:

  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstdio>
  4 #include <cmath>
  5 #include <vector>
  6 #include <cstring>
  7 #include <map>
  8 #include <set>
  9 #include <queue>
 10 #include <algorithm>
 11 using namespace std;
 12 const int maxlongint = 2147483647;
 13 int ans = 0, tot, n, m, st, ed;
 14 int last[11000], h[11000];
 15 struct edge{
 16     int u, v, w, nxt, other; 
 17 }p[510000];
 18 inline int read()
 19 {
 20     int s=0,w=1;
 21     char ch=getchar();
 22     while (ch<='0'||ch>'9')
 23     {
 24         if (ch=='-') w=-1;
 25         ch=getchar();
 26     }
 27     while (ch>='0'&&ch<='9')
 28     {
 29         s=s*10+ch-'0';
 30         ch=getchar();
 31     }
 32     return s*w;
 33 }
 34 void addedge(int u, int v, int w)
 35 {
 36     int k1, k2;
 37     k1 = ++tot;
 38     p[tot].u = u;
 39     p[tot].v = v;
 40     p[tot].w = w;
 41     p[tot].nxt = last[u];
 42     last[u] = tot;
 43     k2 = ++tot;
 44     p[tot].v = u;
 45     p[tot].u = v;
 46     p[tot].w = 0;
 47     p[tot].nxt = last[v];
 48     last[v] = tot;
 49     p[k1].other = k2;
 50     p[k2].other = k1;
 51 }
 52 bool bfs_h()
 53 {
 54     memset(h, 0, sizeof(h));
 55     h[st] = true;
 56     queue<int> q;
 57     q.push(st);
 58     while (! q.empty())
 59     {
 60         int u = q.front();
 61         for (int k = last[u]; k > 0; k = p[k].nxt)
 62         {
 63             int v = p[k].v;
 64             if (p[k].w>0 && h[v] == 0)
 65             {
 66                 h[v] = h[u]+1;
 67                 q.push(v);
 68             }
 69         }
 70         q.pop();
 71     }
 72     return h[ed];
 73 }
 74 int min(int x, int y)
 75 {
 76     if (x < y) return x;
 77     else return y;
 78 }
 79 int findflow(int u, int f)
 80 {
 81     if (u == ed) return f;
 82     int s = 0, t;
 83     for (int k = last[u]; k>0; k = p[k].nxt)
 84     {
 85         int v = p[k].v;
 86         if (p[k].w > 0 && h[v] == h[u]+1 && s < f)
 87         {
 88             t = findflow(v, min(p[k].w, f - s));
 89             s += t;
 90             p[k].w -= t;
 91             p[p[k].other].w += t;
 92         }
 93     }
 94     if (s == 0) h[u] = 0;
 95     return s;
 96 }
 97 int main()
 98 {
 99     ios::sync_with_stdio(false);
100     //freopen(".in","r",stdin);
101     //freopen(".out","w",stdout);
102     n = read();
103     m = read();
104     st = read();
105     ed = read();
106     for (int i = 1; i <= m; i++)
107     {
108         int u, v, w;
109         u = read();
110         v = read();
111         w = read();
112         addedge(u, v, w);
113     }
114     while (bfs_h())
115         ans += findflow(st, maxlongint);
116     cout << ans;
117     return 0;
118 }

 

程序不算长(相对吧。。。),注意吃透。

转载于:https://www.cnblogs.com/yzher/p/8457518.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值