HDU - 3987 Harry Potter and the Forbidden Forest (求割边最少的最小割)

版权声明:本文为博主原创文章,转载请附上注明就行_(:з」∠)_。 https://blog.csdn.net/vocaloid01/article/details/82690059

Harry Potter notices some Death Eaters try to slip into Castle. The Death Eaters hide in the most depths of Forbidden Forest. Harry need stop them as soon as.


The Forbidden Forest is mysterious. It consists of N nodes numbered from 0 to N-1. All of Death Eaters stay in the node numbered 0. The position of Castle is node n-1. The nodes connected by some roads. Harry need block some roads by magic and he want to minimize the cost. But it’s not enough, Harry want to know how many roads are blocked at least.

Input

Input consists of several test cases.

The first line is number of test case.

Each test case, the first line contains two integers n, m, which means the number of nodes and edges of the graph. Each node is numbered 0 to n-1.

Following m lines contains information about edges. Each line has four integers u, v, c, d. The first two integers mean two endpoints of the edges. The third one is cost of block the edge. The fourth one means directed (d = 0) or undirected (d = 1).

Technical Specification

1. 2 <= n <= 1000
2. 0 <= m <= 100000
3. 0 <= u, v <= n-1
4. 0 < c <= 1000000
5. 0 <= d <= 1

Output

For each test case:
Output the case number and the answer of how many roads are blocked at least.

Sample Input

3

4 5
0 1 3 0
0 2 1 0
1 2 1 1
1 3 1 1
2 3 3 1

6 7
0 1 1 0
0 2 1 0
0 3 1 0
1 4 1 0
2 4 1 0
3 5 1 0
4 5 2 0

3 6
0 1 1 0
0 1 2 0
1 1 1 1
1 2 1 0
1 2 1 0
2 1 1 1

Sample Output

Case 1: 3
Case 2: 2
Case 3: 2

做法参考:HDU - 6214 Smallest Minimum Cut

代码:

#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>

using namespace std;

const int MAXN = 1005;
const int INF = 0x3f3f3f3f3f3f3f3f;
 
struct Edge{
	int to,rev;
	long long flow;
	Edge(){}
	Edge(int a,long long b,int c):to(a),flow(b),rev(c){}
};
 
vector<Edge> E[MAXN];
 
inline void Add(int from,int to,long long flow){
	E[from].push_back(Edge(to,flow,E[to].size()));
	E[to].push_back(Edge(from,0,E[from].size()-1));
}
 
int deep[MAXN];
 
bool BFS(int from,int to){
	memset(deep,-1,sizeof deep);
	deep[from] = 0;
	queue<int> Q;
	Q.push(from);
	while(!Q.empty()){
		int t = Q.front();
		Q.pop();
		for(int i=0 ; i<E[t].size() ; ++i){
			Edge& e = E[t][i];
			if(e.flow > 0 && deep[e.to] == -1){
				deep[e.to] = deep[t] + 1;
				Q.push(e.to);
			}
		}
	}
	return deep[to] != -1;
}
 
int iter[MAXN];
 
long long DFS(int from,int to,long long flow){
	if(from == to || flow == 0)return flow;
	for(int &i=iter[from] ; i<E[from].size() ; ++i){
		Edge &e = E[from][i];
		if(e.flow > 0 && deep[e.to] == deep[from]+1){
			int nowflow = DFS(e.to,to,min(flow,e.flow));
			if(nowflow > 0){
				e.flow -= nowflow;
				E[e.to][e.rev].flow += nowflow;
				return nowflow;
			}
		}
	}
	return 0;
}
 
long long Dinic(int from,int to){
	long long sumflow = 0;
	while(BFS(from,to)){
		memset(iter,0,sizeof iter);
		long long t;
		while((t=DFS(from,to,INF)) > 0)sumflow += t;
	}
	return sumflow;
}

int main(){
	
	int T,n,m,Case = 0;
	scanf("%d",&T);
	while(T--){
		scanf("%d %d",&n,&m);
		for(int i=1 ; i<=m ; ++i){
			int a,b,d;
			long long c;
			scanf("%d %d %lld %d",&a,&b,&c,&d);
			Add(a,b,c*(m+1)+1);
			if(d)Add(b,a,c*(m+1)+1);
		}
		printf("Case %d: %lld\n",++Case,Dinic(0,n-1)%(m+1));
		for(int i=0 ; i<=n ; ++i)E[i].clear();
	}
	
	return 0;
}
 

猜你喜欢

转载自blog.csdn.net/vocaloid01/article/details/82690059