洛谷p3376 网络流最大流模板题

链接:https://www.luogu.org/problem/P3376

题目:
题目描述

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

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

样例说明:

洛谷p3376 网络流最大流模板题_第1张图片

题目中存在3条路径:

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

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

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

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


思路:最大流模板题,没啥好说的。

#include
using namespace std;
const int maxn=10010,maxm=100010;
const int INF=0x3f3f3f3f;
int n,m,s,t;
int head[maxn],tot,N;
int dis[maxn];

struct node
{
	int to,next,w;
}edge[2*maxm];//边开大一点,正反向,两倍最好。 


void edge_init()
{
	memset(head,-1,sizeof(head));
	tot=0;N=n;
}

void add_edge(int u,int v,int w)//建边正反向都建边 
{
	edge[tot]=(node){v,head[u],w};
	head[u]=tot++;
	edge[tot]=(node){u,head[v],0};
	head[v]=tot++;
}

int bfs()
{
	for(int i=0;i<=N;i++)
	{
		dis[i]=0;
	 }
	 dis[s]=1;
	 queue<int> que;
	 que.push(s);
	 while(!que.empty())
	 {
	 	int u=que.front();que.pop();
	 	for(int i=head[u];i!=-1;i=edge[i].next)
	 	{
	 		int v=edge[i].to;
	 		if(edge[i].w>0&&dis[v]==0)
	 		{
	 			dis[v]=dis[u]+1;que.push(v);
			 }
		 }
	  } 
	  if(dis[t]!=0) return 1;
	  else return 0;
}

int dfs(int u,int dist)
{
	if(u==t) return dist;
	for(int i=head[u];i!=-1;i=edge[i].next)
	{
		int v=edge[i].to;
		if(dis[v]==dis[u]+1&&edge[i].w!=0)
		{
			int mi=dfs(v,min(dist,edge[i].w));
			if(mi>0)
			{
				edge[i].w-=mi;
				edge[i^1].w+=mi;
				return mi;
			}
		}
	}
	return 0;
}

int dinic()//dinic模板 
{
	int maxflow=0;
	while(bfs())
	{
		while(int mi=dfs(s,INF)) maxflow+=mi;
	}
	return maxflow;
}


int main()
{
	scanf("%d%d%d%d",&n,&m,&s,&t);
	edge_init();
	for(int i=1;i<=m;i++)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		add_edge(a,b,c);
	}
	int fin=dinic();
	printf("%d\n",fin);
	return 0;
}

你可能感兴趣的:(图论,最大流模板题)