码迷,mamicode.com
首页 > 其他好文 > 详细

luogu P3376 【模板】网络最大流

时间:2017-07-17 11:06:43      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:规模   流量   blank   read   define   cap   long   表示   序号   

题目描述

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

输入输出格式

输入格式:

 

第一行包含四个正整数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。

一篇较好博文 :http://www.cnblogs.com/ShaneZhang/p/3755479.html

/*
网络最大流个人理解(并不透彻): 
	
	网络最大流是指网络中最大的可行流,可行流概念很好理解的。 
	增广路:简单来说就是指还可以有流量通过的路径。 
	求最大可行流可采用增广的算法:找出残量网络(还可增加流量),
	即  容量-当前流量  和 一种逆向边(疑惑:逆向边 v-u的流量指u-v的初始当前流量还是0??)  所构成的网络,
	每次找出增广路中的可行流量的min,将此增广路上的边进行增广(+min),直到不存在增广路。 
	至于建立逆向边(并不十分理解)才会使得已经增加了的流量回退,从而找到更大的可行流
	(只要流量在满足网络流概念的情况下增加,则此时的网络中存在的一定是 更 优解)。 
	
*/

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#define ll long long

using namespace std;
const int N=300001;
const int maxn=0x7fffff;

inline int read()
{
	int x=0;char c=getchar();
	while(c<‘0‘||c>‘9‘)c=getchar();
	while(c>=‘0‘&&c<=‘9‘)x=x*10+c-‘0‘,c=getchar();
	return x;
}

int head[N],dis[N];
bool vis[N];
int now=0;
int n,m,S,T;
struct node{
	int u,v,cap,flow,nxt;
}E[N];

inline void add(int u,int v,int w)
{
	E[now].u=u;
	E[now].v=v;
	E[now].cap=w;
	E[now].flow=0;
	E[now].nxt=head[u];
	head[u]=now++;
}

bool bfs(int start,int endd)
{
	for(int i=1;i<=n;i++)
		dis[i]=-1;
	queue<int>Q;
	Q.push(start);
	dis[start]=0;
	while(!Q.empty())
	{
		int topp=Q.front();
		Q.pop();
		for(int i=head[topp];~i;i=E[i].nxt)
		{
			if(dis[E[i].v]==-1&&E[i].cap>E[i].flow)
			{
				vis[E[i].v]=1;
				dis[E[i].v]=dis[topp]+1;
				Q.push(E[i].v);
			}
		}
	}
	if(dis[endd]==-1)
		return 0;
	return 1;
}

int dfs(int start,int minn)
{
	if(start==T||minn<=0)
		return minn;
	int flow=0,f;
	for(int i=head[start];~i;i=E[i].nxt)
	{
		if(dis[start]+1==dis[E[i].v]&&E[i].cap-E[i].flow>0)
		{
			f=dfs(E[i].v,min(minn,E[i].cap-E[i].flow));
			E[i].flow+=f;
			E[i^1].flow-=f;
			flow+=f;
			minn-=f;
			if(minn<=0)
				break;
		}
	}
	return flow;
}

inline void Dinic(int S,int T)
{
	int ansflow=0;
	while(bfs(S,T))
		ansflow+=dfs(S,maxn);
	printf("%d",ansflow);
}

int main()
{
	n=read(),m=read(),S=read(),T=read();
	for(int i=1;i<=n;i++)
		head[i]=-1;
	for(int i=1;i<=m;i++)
	{
		int u=read(),v=read(),w=read();
		add(u,v,w);
		add(v,u,0);
	}
	Dinic(S,T);
	return 0;
}

  

 

luogu P3376 【模板】网络最大流

标签:规模   流量   blank   read   define   cap   long   表示   序号   

原文地址:http://www.cnblogs.com/lyqlyq/p/7193091.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!