最大流Dinic算法
嘿嘿嘿,时隔不久又见到了DInic,再次回顾一下吧
不过这次我倒是不想深究,而是想多做一些题,因为这几次比赛下来,算法不是重点,重点是题目如何转化,算法如何应用,这也是比赛为什么让你带着板子的原因吧,所以算法基本思想掌握了就好,不要去背,一看就能想通就行
Dinic算法通过bfs优先的分层处理,加以当前弧的优化,使得dfs寻找 最大流的更多,不像ff算法dfs效率低下,通过分层使得dfs明确了寻找方向,当前弧的优化,使得dfs寻边效率大大提高
Code
一些基本操作
#include <iostream> #include <cstdio> #include <string.h> #include <queue> #define inf (1 << 28) using namespace std; typedef long long ll; const int maxn = 220; const int maxm = 4e4 + 4e2; int n,m; struct node{ int pre; int to,cost; }e[maxm]; int id[maxn],cnt;
//层数 int flor[maxn]; int cur[maxn];//DFS的优化遍历::当前弧优化 void add(int from,int to,int cost) { e[cnt].to = to; e[cnt].cost = cost; e[cnt].pre = id[from]; id[from] = cnt++; swap(from,to); e[cnt].to = to; e[cnt].cost = 0; e[cnt].pre = id[from]; id[from] = cnt++; }
bfs分层处理
其实明白了思路,这个很简单就能写出来
int bfs(int s,int t) { memset(flor,0,sizeof(flor)); queue < int > q; while(q.size())q.pop(); flor[s] = 1; q.push(s); while(q.size()) { int now = q.front(); q.pop(); for(int i = id[now];~i;i=e[i].pre) { int to = e[i].to; int cost = e[i].cost; if(flor[to] == 0 && cost > 0) { flor[to] = flor[now] + 1; q.push(to); if(to == t)return 1; } } } return 0; }
dfs当前弧度的优化
dfs比较难懂,为什么要懂ff就是因为一切的算法都是以简单算法为基础的优化过来的
value:是s - s’的最大流(起始点为s)
ret:s' - t的残流(起始点为s’)
一层一层的递归,value - ret就是最大流了,具体还是理解代码展现出的思想
记得我第一次看的时候,dinic真的好绝望...看了n多篇博客,最后也没有
int dfs(int s,int t,int value) { //ret表示目前流到s的最大流量,用来计算回溯的时候是否还有可行流 int ret = value; if(s == t || value == 0)return value; int a; for(int &i = cur[s];~i;i = e[i].pre) { int to = e[i].to; int cost = e[i].cost; if(flor[to] == flor[s] + 1 && (a = dfs(to,t,min(ret,cost)))) { e[i].cost -= a; e[i^1].cost += a; ret -= a; if(ret == 0)break; } } //s点后面没有可行的流了,flor[s] = 0就表示废掉了这个点 if(ret == value) flor[s] = 0; return value - ret; }
DInic算法就是基于bfs来dfs的
int dinic(int s,int t) { ll ret = 0; while(bfs(s,t)) { memcpy(cur,id,sizeof(id)); ret += dfs(s,t,inf); } return ret; }
其他的就简单啦
void init() { memset(id,-1,sizeof(id)); cnt = 0; } int main() { while(~scanf("%d%d",&m,&n)) { init(); int a,b,x; for(int i = 1;i <= m;++i) { scanf("%d%d%d",&a,&b,&x); add(a,b,x); } ll ret = dinic(1,n); printf("%lld\n",ret); } return 0; }