UVA10480——最大流最小割(路径输出)板子题

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1421

The regime of a small but wealthy dictatorship has been abruptly overthrown by an unexpected rebellion. Because of the enormous disturbances this is causing in world economy, an imperialist military super power has decided to invade the country and reinstall the old regime. For this operation to be successful, communication between the capital and the largest city must be completely cut. This is a difficult task, since all cities in the country are connected by a computer network using the Internet Protocol, which allows messages to take any path through the network. Because of this, the network must be completely split in two parts, with the capital in one part and the largest city in the other, and with no connections between the parts. There are large differences in the costs of sabotaging different connections, since some are much more easy to get to than others. Write a program that, given a network specification and the costs of sabotaging each connection, determines which connections to cut in order to separate the capital and the largest city to the lowest possible cost.
Input
Input file contains several sets of input. The description of each set is given below. The first line of each set has two integers, separated by a space: First one the number of cities, n in the network, which is at most 50. The second one is the total number of connections, m, at most 500. The following m lines specify the connections. Each line has three parts separated by spaces: The first two are the cities tied together by that connection (numbers in the range 1−n). Then follows the cost of cutting the connection (an integer in the range 1 to 40000000). Each pair of cites can appear at most once in this list. Input is terminated by a case where values of n and m are zero. This case should not be processed. For every input set the capital is city number 1, and the largest city is number 2.
Output
For each set of input you should produce several lines of output. The description of output for each set of input is given below: The output for each set should be the pairs of cities (i.e. numbers) between which the connection should be cut (in any order), each pair on one line with the numbers separated by a space. If there is more than one solution, any one of them will do. Print a blank line after the output for each set of input.
Sample Input
5 8

1 4 30

1 3 70

5 3 20

4 3 5

4 5 15

5 2 10

3 2 25

2 4 50

5 8

1 4 30

1 3 70

5 3 20

4 3 5

4 5 15

5 2 10

3 2 25

2 4 50

0 0
Sample Output
4 1

3 4

3 5

3 2


4 1

3 4

3 5

3 2

 

题目翻译:

一个小而富有的独裁政权突然被一场意想不到的叛乱推翻。由于这在世界经济中引起了巨大的动乱,帝国主义的军事超级大国决定侵略这个国家,重新建立旧政权。为了使这项行动取得成功,首都和最大城市之间的通讯必须完全中断。这是一项艰巨的任务,因为该国的所有城市都通过使用互联网协议的计算机网络连接,允许消息通过网络走任何路径。因此,网络必须完全分成两部分,一部分是首都,另一部分是最大的城市,两部分之间没有联系。破坏不同连接的成本存在很大差异,因为有些连接比其他连接容易得多。编写一个程序,在给定网络规格和破坏每个连接的成本的情况下,确定要切断的连接,以便将首都和最大城市分离到尽可能低的成本。

输入              

输入文件包含多组输入。每组的说明如下。每组的第一行有两个整数,用一个空格隔开:第一行是城市数目,网络中n个,最多50个。第二个是连接总数,m,最多500个。以下M行指定了连接。每一行有三个部分,用空格隔开:前两个部分是通过该连接连接在一起的城市(数字在1-n范围内)。然后按照切断连接的成本(1到40000000范围内的整数)。在这个列表中,每对CIT最多只能出现一次。输入以n和m值为零的情况终止。不应处理此案例。对于每个输入集,首都是城市1,最大的城市是城市2

输出

 对于每一组输入,您应该产生多行输出。每一组输入的输出描述如下:每一组的输出应该是一对城市(即数字),在两个城市之间的连接应该被切断(以任何顺序),每对城市在一行上,数字之间用空格隔开。如果有多个解决方案,它们中的任何一个都可以。在每一组输入的输出后打印一个空行 

 

比较经典的最小割最大流题。

题意比较坑,其实就是给你n个点和m条边。

然后让你求出把结点1和结点2割开的最小花费的边上的路径。

这里给的是基于邻接矩阵的EK算法的实现。

#include 
#include
#include
using namespace std;
const int INF=0x3f3f3f3f;
int G[1005][1005],pre[1005],x[1005],y[1005];
int flow[1005][1005];
int a[1005];
int S=1,T=2;
int n;
void EK(){
	queue q;
	memset(flow,0,sizeof(flow));
//	int ans=0;
	while(1){
		memset(a,0,sizeof(a));
//		memset(pre,-1,sizeof(pre));
		while(!q.empty()) q.pop();
		a[S]=INF;
		q.push(S);
		while(!q.empty()){
			int now=q.front();
			q.pop();
//			if(now==T) break;
			for(int i = 1;i<=n;++i){
				if(!a[i]&&G[now][i]>flow[now][i]){
					pre[i]=now;
					a[i]=min(a[now],G[now][i]-flow[now][i]);
					q.push(i);
				}
			}
		}
		if(a[T]==0) break;
		for(int i = T;i!=S;i=pre[i]){
			flow[pre[i]][i]+=a[T];
			flow[i][pre[i]]-=a[T];
		}
//		ans+=a[T];
	}
//	return ans;
}
int main(int argc, char** argv) {
	int m;
	while(~scanf("%d%d",&n,&m)&&n&&m){
		memset(G,0,sizeof(G));
		for(int i = 0;i


 

你可能感兴趣的:(网络流)