Dinic算法模板
邻接矩阵形式
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int N=205;
const int INF=0x3f3f3f3f;
int g[N][N],layer[N];
bool vis[N];
int n,m;//1是源点 n是汇点
bool CounterLayer()
{
queue<int>q;
memset(layer,-1,sizeof(layer));
layer[1]=0;
q.push(1);
while(!q.empty())
{
int v=q.front();
q.pop();
for(int i=1;i<=n;i++)
if(g[v][i]>0&&layer[i]==-1)
{
layer[i]=layer[v]+1;
if(i==n)//分层到汇点即可
return true;
else
q.push(i);
}
}
return false;
}
int Dinic()
{
int ans=0;
vector<int>q;
while(CounterLayer())//只要能分层
{
q.push_back(1);//源点入栈
while(!q.empty())
{
int u=q.back();
if(u==n)//如果u是汇点,在路径中找容量最小边
{
int temp=INF;
int st;//容量最小边的起点
for(int i=1;i<q.size();i++)
{
int vs=q[i-1];
int ve=q[i];
if(g[vs][ve]>0&&temp>g[vs][ve])
temp=g[st=vs][ve];
}
//改图
ans+=temp;
for(int i=1;i<q.size();i++)
{
int vs=q[i-1];
int ve=q[i];
g[vs][ve]-=temp;
g[ve][vs]+=temp;
}
//退栈到 st 成为栈顶,以便继续dfs
while(!q.empty()&&q.back()!=st)
q.pop_back();
}
else//如果u不是汇点
{
int i;
for(i=1;i<=n;i++)//往下一层结点走
if(g[u][i]>0&&layer[i]==layer[u]+1)
{
q.push_back(i);
break;
}
if(i>n)//找不到下一个结点
{
layer[q.back()]=-1;
q.pop_back();
}
}
}
}
return ans;
}
int main()
{
while(~scanf("%d%d",&m,&n))
{
int s,e,c;
memset(g,0,sizeof(g));
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&s,&e,&c);
g[s][e]+=c;
}
printf("%d\n",Dinic());
}
return 0;
}
邻接表形式(前向星实现)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=205;
const int INF=0x3f3f3f3f;
int layer[N];
bool vis[N];
int n,m;//1是源点 n是汇点
//前向星实现邻接表
int M;
int head[N];
struct Edge{
int from,to,next,w;
}edge[N*N];
void add(int from,int to,int w)
{
edge[M].next=head[from];
edge[M].to=to;
edge[M].w=w;
head[from]=M++;
}
bool CountLayer()//分层
{
queue<int>q;
memset(layer,-1,sizeof(layer));
layer[1]=0;
q.push(1);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int k=head[u];k!=-1;k=edge[k].next)
{
int v=edge[k].to;
int w=edge[k].w;
if(w>0&&layer[v]==-1)
{
layer[v]=layer[u]+1;
if(v==n)
return true;
else
q.push(v);
}
}
}
return false;
}
int Dinic(int s,int t)
{
int ans=0;
int q[N*N];
while(CountLayer())
{
int k,u,v,back,size=1;
while(size)
{
u=(size==1)?s:edge[q[size-1]].to;
//u是汇点
if(u==t)
{
int temp=INF;
for(int i=1;i<size;i++)
{
k=q[i];
if(edge[k].w>0&&edge[k].w<temp)
{
temp=edge[k].w;
back=i;
}
}
//改图
for(int i=1;i<size;i++)
{
k=q[i];
edge[k].w-=temp;
edge[k^1].w+=temp;
}
ans+=temp;
size=back;
}
//u不是汇点
else
{
for(k=head[u];k!=-1;k=edge[k].next)
{
int v=edge[k].to;
if(edge[k].w>0&&layer[v]==layer[u]+1)
break;
}
if(k!=-1)
q[size++]=k;
else
{
layer[u]=-1;
size--;
}
}
}
}
return ans;
}
int main()
{
while(~scanf("%d%d",&m,&n))
{
int s,e,c;
M=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&s,&e,&c);
add(s,e,c);
add(e,s,0);//添加反向边
}
printf("%d\n",Dinic(1,n));
}
return 0;
}