您的位置:首页 > 理论基础 > 计算机网络

P3376 【模板】网络最大流

2017-07-29 15:53 471 查看

题目描述

如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。

输入输出格式

输入格式:

第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。

接下来M行每行包含三个正整数ui、vi、wi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi)

输出格式:

一行,包含一个正整数,即为该网络的最大流。

输入输出样例

输入样例#1:

4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 40


输出样例#1:

50


说明

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=10,M<=25

对于70%的数据:N<=200,M<=1000

对于100%的数据:N<=10000,M<=100000

样例说明:



题目中存在3条路径:

4-->2-->3,该路线可通过20的流量

4-->3,可通过20的流量

4-->2-->1-->3,可通过10的流量(边4-->2之前已经耗费了20的流量)

故流量总计20+20+10=50。输出50。

看了几本教材发现都没有用边表去写网络流的,于是自己琢磨了很长时间,

用的是Dinic算法

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#define lli long long int
using namespace std;
const int MAXN=300001;
const int maxn=0x7fffff;
void read(int &n)
{
char c='+';int x=0;bool flag=0;
while(c<'0'||c>'9')
{c=getchar();if(c=='-')flag=1;}
while(c>='0'&&c<='9')
{x=x*10+c-48;c=getchar();}
flag==1?n=-x:n=x;
}
struct node
{
int u,v,flow,cap,nxt;
}edge[MAXN];
int head[MAXN];
int num=0;
int n,m,S,T;
int dis[MAXN];
int vis[MAXN];
int cur[MAXN];
void add_edge(int x,int y,int z)
{
edge[num].u=x;
edge[num].v=y;
edge[num].cap=z;
edge[num].flow=0;
edge[num].nxt=head[x];
head[x]=num++;
}
bool bfs(int bg,int ed)
{
memset(dis,-1,sizeof(dis));
queue<int>q;
q.push(bg);
dis[bg]=0;
while(!q.empty())
{
int p=q.front();
q.pop();
for(int i=head[p];i!=-1;i=edge[i].nxt)
{
if(dis[edge[i].v]==-1&&edge[i].cap>edge[i].flow)
{
vis[edge[i].v]=1;
dis[edge[i].v]=dis[edge[i].u]+1;
q.push(edge[i].v);
}
}
}
if(dis[ed]==-1)
return 0;
else return 1;
}
int dfs(int now,int a)// a:所有弧的最小残量
{
if(now==T||a<=0)
return a;

int flow=0,f;
for(int i=head[now];i!=-1;i=edge[i].nxt)
{
if(dis[now]+1==dis[edge[i].v]&&edge[i].cap-edge[i].flow>0)
{
f=dfs(edge[i].v,min(a,edge[i].cap-edge[i].flow));
edge[i].flow+=f;
edge[i^1].flow-=f;
flow+=f;
a-=f;
if(a<=0)break;
}
}
return flow;
}
void Dinic(int S,int T)
{
int ansflow=0;
for(int i=1;i<=n;i++)
cur[i]=head[i];
while(bfs(S,T))// 求出层级
ansflow+=dfs(S,maxn);
printf("%d",ansflow);

}
int main()
{
read(n);read(m);
//    swap(n,m);
//    S=1;T=m;
read(S);read(T);
for(int i=1;i<=n;i++)
head[i]=-1;
for(int i=1;i<=m;i++)
{
int x,y,z;
read(x);read(y);read(z);
add_edge(x,y,z);
add_edge(y,x,0);
}
Dinic(S,T);
return 0;
}


update in 2017.7.29

补充一份加了当前弧优化&&把cap和flow两个变量合成一个的代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
const int MAXN=10000001;
const int MAXM=30000001;
const int maxn=0x7fffff;
inline void read(int &n)
{
char c='+';int x=0;bool flag=0;
while(c<'0'||c>'9'){c=getchar();if(c=='-')flag=1;}
while(c>='0'&&c<='9'){x=x*10+(c-48);c=getchar();}
flag==1?n=-x:n=x;
}
struct node
{
int u,v,f,nxt;
}edge[MAXM];
int head[MAXN];
int num=0;
int n,m,s,t;
inline void add_edge(int x,int y,int z)
{
edge[num].u=x;
edge[num].v=y;
edge[num].f=z;
edge[num].nxt=head[x];
head[x]=num++;
}
int ans=0;
int deep[MAXN];
int cur[MAXN];
inline bool bfs()
{
memset(deep,0,sizeof(deep));
deep[s]=1;
queue<int>q;
q.push(s);
while(q.size()!=0)
{
int p=q.front();
q.pop();
for(int i=head[p];i!=-1;i=edge[i].nxt)
if(!deep[edge[i].v]&&edge[i].f)
{
deep[edge[i].v]=deep[edge[i].u]+1;
q.push(edge[i].v);
}

}
return deep[t];
}
int dfs(int now,int a)
{
if(now==t||a<=0)
return a;
int totflow=0,curflow;
for(int &i=cur[now];i!=-1;i=edge[i].nxt)
{
if(edge[i].f&&deep[edge[i].v]==deep[edge[i].u]+1)
{
curflow=dfs(edge[i].v,min(a,edge[i].f));
edge[i].f-=curflow;
edge[i^1].f+=curflow;
totflow+=curflow;
a-=curflow;
if(a<=0) break;
}
}
return totflow;
}
inline void Dinic()
{
while(bfs())
{
for(int i=0;i<=n;i++)
cur[i]=head[i];
ans+=dfs(s,maxn);
}

printf("%d",ans);
}
int main()
{
read(n);read(m);read(s);read(t);
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++)
{
int x,y,z;
read(x);read(y);read(z);
add_edge(x,y,z);
add_edge(y,x,0);
}
Dinic();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: