网络流模板提
Sap模板:
const int N = 220 , M = 2020;
#define inf (1<<29)
int gap[N] , dis[N] , pre[N] , cur[N];
int NV , n , m;
struct Edge {
int v , w , next;
Edge () {}
Edge(int v,int w,int next):v(v),w(w),next(next) {}
}edge[M];
int maxflow;
int E , head[N];
void addedge(int u,int v,int w) {
edge[E] = Edge(v,w,head[u]);
head[u] = E ++;
edge[E] = Edge(u,0,head[v]);
head[v] = E++;
}
void init() {
E = 0;
memset(head,-1,sizeof(int)*(NV+1));
}
int sap(int st,int en) {
memset(dis,0,sizeof(int)*(NV+1));
memset(gap,0,sizeof(int)*(NV+1));
for(int i=0;i<NV;i++) cur[i] = head[i];
int u = pre[st] = st , maxflow = 0 , aug = inf;
gap[0] = NV;
while(dis[st] < NV) {
loop: for(int &i=cur[u];i!=-1;i=edge[i].next) {
int v = edge[i].v;
if(edge[i].w && dis[u] == dis[v] + 1) {
aug = aug<edge[i].w?aug:edge[i].w;
pre[v] = u;
u = v;
if(v == en) {
maxflow += aug;
for(u=pre[u];v!=st;v=u,u=pre[u]) {
edge[cur[u]].w -= aug;
edge[cur[u]^1].w += aug;
}
aug = inf;
}
goto loop;
}
}
int mindis = NV;
for(int i=head[u];i!=-1;i=edge[i].next) {
int v = edge[i].v;
if(edge[i].w && mindis > dis[v]) {
cur[u] = i;
mindis = dis[v];
}
}
if( --gap[dis[u]] == 0 ) break;
gap[ dis[u] = mindis+1 ] ++;
u = pre[u];
}
return maxflow;
}
int main() {
while(~scanf("%d%d",&m,&n)) {
NV = n + 1;
init();
for(int i=0;i<m;i++) {
int u , v , w;
scanf("%d%d%d",&u,&v,&w);
u -- ; v -- ;
addedge(u , v , w);
}
printf("%d\n",sap(0,n-1)); }
return 0;
}
dinic算法
dinic算法不断重复一下过程:
首先从源点沿着可增广边做一遍广搜,给每个点标记一个距离。如果遍历不到汇点,既找不到增广路,算法结束。
在增广的时候,只选择距离恰好是自己距离加一的点扩展。这样保证了每次以最短路增广。其次在找到了一条增广路后,并不是立刻回退到源点,而是寻找到增光路上第一个满流的边的起点继续访问。
dinic模板:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define inf (1<<29)
const int N = 220 , M = 20200;
struct Edge {
int v ,f , next;
Edge () {}
Edge (int v,int f,int next) :v(v),f(f),next(next) {};
}edge[M];
int E , head[N];
void init() {
E = 0; memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int f) {
edge[E] = Edge(v,f,head[u]); head[u] = E++;
edge[E] = Edge(u,0,head[v]); head[v] = E++;
}
int n , m , NV , st , ed;
queue <int> q;
bool vis[N];
int dist[N];
void bfs() {
memset(dist,0,sizeof(dist));
while(!q.empty()) q.pop();
vis[st] = true;
q.push(st);
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i=head[u];i!=-1;i=edge[i].next) {
if(edge[i].f && !vis[edge[i].v]) {
q.push(edge[i].v);
dist[edge[i].v] = dist[u] + 1;
vis[edge[i].v] = true;
}
}
}
}
int dfs(int u,int delta) {
if(u == ed) return delta;
else {
int ret = 0;
for(int i=head[u];delta && i!=-1;i=edge[i].next) {
if(edge[i].f && dist[edge[i].v] == dist[u] + 1) {
int dd = dfs(edge[i].v ,min(edge[i].f,delta));
edge[i].f -= dd;
edge[i^1].f += dd;
delta -= dd;
ret += dd;
}
}
return ret;
}
}
int maxflow() {
int ret = 0;
while(true) {
memset(vis,0,sizeof(vis));
bfs();
if(!vis[ed]) return ret;
ret += dfs(st ,ed);
}
}
int main() {
while(~scanf("%d%d",&m,&n)) {
init();
st = 1; ed = n;
while(m--) {
int u , v , f;
scanf("%d%d%d",&u,&v,&f);
addedge(u,v,f);
}
int ans = maxflow();
printf("%d\n" , ans);
}
return 0;
}