1. 程式人生 > >POJ1273 最大流模板題 初學網路流~

POJ1273 最大流模板題 初學網路流~

題意 不細說了,就是源是1,匯點是m的最大流模板

思路 初學網路流,拿這題練練手。

  總結下EdmondsKarp演算法幾個要注意的點:

           (1)演算法本質就是利用BFS不停地找增廣路,直到找不到為止。

           (2)每次BFS後更新增廣路時,一定注意減去或加上的都是最後Terminal得到流量。

           (3)用連線表存的時候,為了把平行邊存在相鄰位置上,可能會增加平行邊,為了避免這一點,可以在輸入的時候做些處理,不過對最大流來說感覺不處理也不會有什麼太大問題。當然用鄰接矩陣來存就好辦了,對平行邊累加流量就好了。

                對這題來說,就是注意輸入是多組的.....還有有平行邊的存在

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
#define maxn 205
#define maxm 500
const int inf = 0x3f3f3f3f;

struct Edge{
	int fr,to,val;
	int next;
	Edge(int fr=0,int to=0,int val=0,int next=-1):fr(fr),to(to),val(val),next(next){
	}
	void set(int f=0,int t=0,int v=0,int n=-1)
	{
		fr = f;
		to = t;
		val = v;
		next = n;
	}
}edge[maxm];

int g[maxn];
int n,m;

void addEdge(){
	int f,t,v,i,j;
	int now = 0;
	memset(g,-1,sizeof(g));
	for(i=0;i<m;i++)
	{
		scanf("%d%d%d",&f,&t,&v);
		edge[now].set(f,t,v,g[f]);
		g[f] = now++;
		//這裡這樣處理會造成重邊 
		edge[now].set(t,f,0,g[t]);
		g[t] = now++;
	}
} 

int flow[maxn];
int path[maxn];


int bfs(int st,int ter)
{
	memset(path,-1,sizeof(path));
	flow[st] = inf;
	queue<int> q;
	q.push(st);
	while(q.size()!=0 && path[ter] ==-1)
	{
		int now = q.front();
		q.pop();
		for(int e = g[now];e != -1;e=edge[e].next)
		{
			//若這點被訪問過或者這條邊殘量為0則跳過 
			if(path[edge[e].to]!=-1 || edge[e].val==0 || edge[e].to == st)
				continue;
			flow[edge[e].to] = min(flow[now],edge[e].val); 
			path[edge[e].to] = e;
			q.push(edge[e].to);
		}
	}
	while(q.size())
		q.pop();
	if(path[ter] == -1)
		return -1;
	return flow[ter];
}

int EdmondsKarp(int st,int ter)
{
	int sum = 0;
	path[st] = -1;
	while(bfs(st,ter)>=0)
	{
		sum += flow[ter];
		//構建新的殘量圖 
		for(int e=path[ter];e!=-1;e=path[edge[e].fr])
		{
			edge[e].val -= flow[ter];
			edge[e^1].val += flow[ter];
		}
	}
	return sum;
}


int main()
{
	while(scanf("%d%d",&m,&n)==2)
	{
		addEdge();
		cout<<EdmondsKarp(1,n)<<endl;
	}
	return 0;
}

鄰接矩陣實現

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 900;
const int maxm = 10000;
const int inf = 0x3f3f3f3f;


struct EdmondsKarp{
	//用到外部變數maxn,maxm,具體使用不非得按照模板 
	int n,m;
	int g[maxn][maxn];
	int flow[maxn];
	int path[maxn];
	queue<int> q; 
	void init(int nn=0)
	{
		n = nn;
		memset(g,0,sizeof(g));
		memset(flow,0,sizeof(flow));
		memset(path,-1,sizeof(path));
	}
	void addOne(int u,int v,int yuan)
	{
		g[u][v] += yuan;
		m += 2; 
	}
	
	int bfs(int s,int t)
	{
		int i;
		memset(path,-1,sizeof(path));
		flow[s] = inf;
		//如果不加這句話,bfs內部就要一共三個判斷 
		path[s] = s; 
		q.push(s);
		while(q.size()>0)
		{
			int tmp = q.front();
			q.pop();
			//這裡i從0開始還是1開始,視情況而定 
			for(i=0;i<n;i++)
			{
				if(g[tmp][i]>0 && path[i]==-1)
				{
					flow[i] = min(g[tmp][i],flow[tmp]);
					path[i] = tmp;
					q.push(i);
					if(i==t)
					{
						break;
					}
				}	
			}
			if(path[t] != -1)
				break;
		}
		while(q.size()>0)
			q.pop();
		if(path[t] == -1)
			return 0;
		else	
			return flow[t];
	}
	
	int go(int s,int t)
	{
		int ret = 0;
		while(bfs(s,t))
		{
			int now = path[t];
			int pre = t;
			ret += flow[t];
			while(pre != s)
			{
				g[now][pre] -= flow[t];
				g[pre][now] += flow[t];
				pre = now;
				now = path[now];
			}
		}
		return ret;
	}
	
}edk;

int main()
{
	int n,m;
	while(scanf("%d%d",&m,&n) == 2)
	{
		edk.init(n);
		for(int i=0;i<m;i++)
		{
			int u,v,c;
			scanf("%d%d%d",&u,&v,&c);
			edk.addOne(u-1,v-1,c);
		}
		cout<<edk.go(0,n-1)<<endl;
	}
}