HDU Flow Problem

Problem Description

Network flow is a well-known difficult problem for ACMers. Given a graph, your task is to find out the maximum flow for the weighted directed graph.

Input

The first line of input contains an integer T, denoting the number of test cases.
For each test case, the first line contains two integers N and M, denoting the number of vertexes and edges in the graph. (2 <= N <= 15, 0 <= M <= 1000)
Next M lines, each line contains three integers X, Y and C, there is an edge from X to Y and the capacity of it is C. (1 <= X, Y <= N, 1 <= C <= 1000)

Output

For each test cases, you should output the maximum flow from source 1 to sink N.

Sample Input

2
3 2
1 2 1
2 3 1
3 3
1 2 1
2 3 1
1 3 1

Sample Output

Case 1: 1
Case 2: 2

网络流最大流入门,裸裸的板子题,套紫书的板子就可以

#include<bits/stdc++.h>
#define INF 0x7fffffff
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
struct edge {
	int from, to, cap, flow;
	edge (int _from, int _to, int _cap, int _flow):from(_from), to(_to), cap(_cap), flow(_flow){}
};
struct EdmondsKarp {
	int n, m;
	vector <edge> edges;        // 边数的两倍 
	vector <int>  g[maxn];		// g[i][j] 表示节点 i 的第 j 条边在 e 数组中的位置 
	int a[maxn];				// 当起点到 i 的可改进量 
	int p[maxn];				// 最短路树上 p 的入弧编号 
	void init(int n)
	{
		for(int i = 0;i <= n;i ++)
			g[i].clear();
		edges.clear();
	}
	void addEdge(int from, int to, int cap)
	{
		edges.push_back(edge(from, to, cap, 0));
		edges.push_back(edge(to, from, 0, 0));
		m = edges.size();
		g[from].push_back(m - 2);  // 将每一条边的编号存下来 
		g[to].push_back(m - 1);	   // m - 1 肯定是奇数 不难发现: (m - 1) ^ 1 = (m - 2) 
	}							   // (m - 2) ^ 1 = (m - 1) 
	int maxflow(int s, int t)
	{
		int flow = 0;
		while(1)
		{
			queue <int> q;
			q.push(s);
			memset(a, 0, sizeof(a));
			a[s] = INF;
			while(!q.empty())
			{
				int x = q.front(); q.pop();
				for(int i = 0;i < g[x].size();i ++)
				{
					edge &e = edges[g[x][i]];
					if(!a[e.to] && e.cap > e.flow)		 
					{
						p[e.to] = g[x][i];			// 存下路径 
						a[e.to] = min(a[x], e.cap - e.flow); // emmm...从起点到终点选出最小的可通过流量 
						q.push(e.to);
					}
				}
				if(a[t]) break;		// 当到达终点时 a[t] 必然不为 0 ,由此可推出 
			}
			if(!a[t]) break; 		// 当 a[t] 为 0 ,则说明没有到达,不存在解 
			for(int u = t;u != s;u = edges[p[u]].from) // 按路径回溯,修改流量 
			{
				edges[p[u]].flow += a[t];
				edges[p[u] ^ 1].flow -= a[t]; //  原因同上 
			}
			flow += a[t];
		}
		return flow;
	}
}EK;
int main()
{
	int T;
	scanf("%d", &T);
	for(int t = 1;t <= T;t ++)
	{
		int n, m;
		scanf("%d%d", &n, &m);
		EK.init(n);
		for(int i = 0;i < m;i ++)
		{
			int a, b, c;
			scanf("%d%d%d", &a, &b, &c);
			EK.addEdge(a, b, c);
		}
		printf("Case %d: ", t);
		printf("%d\n", EK.maxflow(1, n));
	}
    return 0;
}
 

猜你喜欢

转载自blog.csdn.net/qq_41695941/article/details/81633816
今日推荐