这题可以作为网络流模板看,这里贴一下自己的dinic模板
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int inf=0x3fffffff,N=400,M=500;
int d[N],head[M],e[M],next[M],ver[M];
int s,t,m,n,tot=1,maxflow=0;
void add (int u,int v,int w) {
ver[++tot]=v;e[tot]=w;next[tot]=head[u];head[u]=tot;
ver[++tot]=u;e[tot]=0;next[tot]=head[v];head[v]=tot;//要在开头++tot与下面的tot初始化对应
}
bool bfs () {
queue<int> q;
memset(d,0,sizeof(d));
q.push(s); d[s]=1;
while (!q.empty()) {
int x=q.front(); q.pop();
for (int i=head[x];i;i=next[i])
if (e[i]&&!d[ver[i]]) {
q.push(ver[i]);
d[ver[i]]=d[x]+1;
if (ver[i]==t) return 1;
}
}
return 0;
}
int dinic (int x,int f) {
int rest=f;
if (x==t) return f;
for (int i=head[x];i&&rest;i=next[i])
if (e[i]&&d[ver[i]]==d[x]+1) {
int now=dinic(ver[i],min(e[i],rest));
if (!now) d[ver[i]]=0;//剪枝
e[i]-=now;
e[i^1]+=now;
rest-=now;
}
return f-rest;
}
int main () {
int u,v,w,tmp;
while (scanf("%d%d",&m,&n)!=EOF) {
s=1,t=n,tot=1,maxflow=0;//这里tot要初始化成1,与上面的++tot对应,这种存法忽略0,1两个存储单元,但能得到一些有意思的用处,见代码下面
memset(head,0,sizeof(head));
for (int i=1;i<=m;i++) {
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
while (bfs())
while (tmp=dinic(s,inf)) maxflow+=tmp;
printf("%d\n",maxflow);
}
}
之前提到的有意思的性质:1、head数组可以初始化成0而不是-1,敲代码的时候感觉要舒服一些~
2、如果节点从1开始标号,那么对于结点i,2*i就代表指向这个结点的正向边。这个做法在 Codehunter 舞动的夜晚 有体现