1. 程式人生 > >Dinic法求最大流

Dinic法求最大流

 經過先對圖進行分層處理,我們在進行搜尋的時候 就會更加的舒服了

(當然 ,程式碼我省略了一版,這是最終形態了。。每條路也都是用結構體實現的)

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
 
#define MAXN 210
#define INF 0x3f3f3f3f
 
struct Edge
{
	int st, ed;//開始 結束
	int c;//權值
	int next;//下一個節點
}edge[MAXN << 1];
 
int n, m;
int s, t;
int ans;
int e = 0; 
int head[MAXN];//建立連結串列
int d[MAXN];//用來分層
 
void init()
{
	int a, b, c; 
	s = 1;
	t = m;
	e = 0;
	ans = 0;
	memset(head, -1, sizeof(head));
	for(int i = 1; i <= n; i++)//建立一個
	{
		scanf("%d%d%d", &a, &b, &c);
		edge[e].st = a;
		edge[e].ed = b;
		edge[e].c = c;
		edge[e].next = head[a];
		head[a] = e++;
		edge[e].st = b;
		edge[e].ed = a;
		edge[e].next = head[b];
		head[b] = e++;
	}
}
 
int bfs()
{
	memset(d, -1, sizeof(d));
	queue<int> q;
	d[s] = 0;
	q.push(s);
	int i;
	int cur;
	while(!q.empty())//BFS
	{
		cur = q.front();
		q.pop();
		for(i = head[cur]; i != -1; i = edge[i].next)
		{
			if(d[edge[i].ed] == -1 && edge[i].c > 0)
			{
				d[edge[i].ed] = d[cur] + 1; //對圖進行分層處理
				q.push(edge[i].ed);
			}	
		}
	}
	if(d[t] < 0)
		return 0;
	return 1;
}
 
int dinic(int x, int flow)
{
	if(x == t)
		return flow;
	int i, a;
	for(i = head[x]; i != -1; i = edge[i].next)
	{
		if(d[edge[i].ed] == d[x] + 1 && edge[i].c > 0 && (a = dinic(edge[i].ed, min(flow, edge[i].c))))
        //首先 要確保我們在搜尋時沒有走“回頭路” 而且可以到達終點,同時路是連通的
		{
			edge[i].c -= a;
			edge[i ^ 1].c += a;//反向增加容量 異或運算取反
			return a;	
		}
	}
	return 0;
}
 
void solve()//這段寫的非常具有大牛風格
{
	while(scanf("%d%d", &n, &m) != EOF)
	{
		init();
		while(bfs())
		{
			int increment;
			increment = dinic(1, INF);
				ans +=  increment; //記錄總共的流量和(即最大流量)
		}
		printf("%d\n", ans);
	}
}
 
int main()
{
	solve();
	return 0;
}