ACM Contest and Blackout(最小和次小生成树)

该博客主要探讨了ACM竞赛中为确保学校电力供应而建立可靠电源的问题。文章介绍了如何通过构建最小生成树和次小生成树来解决这一问题。最小生成树可以通过Kruskal或Prim算法实现,而次小生成树的获取需要从最小生成树中移除一条边并添加未使用的边。代码示例展示了如何在C++中实现这一过程,通过遍历和比较找到次小生成树的总成本。
摘要由CSDN通过智能技术生成

ACM Contest and Blackout (最小和次小生成树)

In order to prepare the “The First National ACM School Contest” (in 20??) the major of the city decided to provide all the schools with a reliable source of power. (The major is really afraid of blackoutsJ). So, in order to do that, power station “Future” and one school (doesn’t matter which one) must be connected; in addition, some schools must be connected as well.
You may assume that a school has a reliable source of power if it’s connected directly to “Future”, or to any other school that has a reliable source of power. You are given the cost of connection between some schools. The major has decided to pick out two the cheapest connection plans – the cost of the
connection is equal to the sum of the connections between the schools. Your task is to help the major— find the cost of the two cheapest connection plans.
Input
The Input starts with the number of test cases, T (1 < T < 15) on a line. Then T test cases follow. The first line of every test case contains two numbers, which are separated by a space, N (3 < N < 100) the number of schools in the city, and M the number of possible connections among them. Next M lines contain three numbers Ai, Bi, Ci, where Ci is the cost of the connection (1 < Ci < 300) between schools Ai and Bi . The schools are numbered with integers in the range 1 to N.
Output
For every test case print only one line of output. This line should contain two numbers separated by a single space – the cost of two the cheapest connection plans. Let S1 be the cheapest cost and S2 the next cheapest cost. It’s important, that S1 = S2 if and only if there are two cheapest plans, otherwise S1 < S2. You can assume that it is always possible to find the costs S1 and S2.
Sample Input
2
5 8
1 3 75
3 4 51
2 4 19
3 2 95
2 5 42
5 4 31
1 2 9
3 5 66
9 14
1 2 4
1 8 8
2 8 11
3 2 8
8 9 7
8 7 1
7 9 6
9 3 2
3 4 7
3 6 4
7 6 2
4 6 14
4 5 9
5 6 10
Sample Output
110 121
37 37

题意: 求最小生成树和次小生成树,最小直接套模板即可,说一下如何求次小生成树,次小生成树与最小生成树其实就是相差一条边,就是去掉最小生成树中的某一边,再加一条没用过的边,至于去哪一条边,就得遍历一遍,比较得结果了

AC代码:

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int f[11000],n,book[11000];
char c,d;
struct pp
{
	int a,b,c;
} p[11000];
bool cmp(pp xx,pp yy)
{
	return xx.c<yy.c;
}
void init()
{
	int i;
	for(i=1; i<=n; i++)
		f[i]=i;
}
int find(int x)
{
	if(f[x]==x)
		return x;
	else
		return f[x]=find(f[x]);
}
void merge(int x,int y)
{
	int xx,yy;
	xx=find(x);
	yy=find(y);
	if(xx!=yy)
		f[yy]=xx;
}
int main()
{
	int m,t,i,j,k;
	scanf("%d",&t);
	while(t--)
	{
		memset(book,0,sizeof(book));
		scanf("%d%d",&n,&m);
		init();
		for(i=0; i<m; i++)
			scanf("%d%d%d",&p[i].a,&p[i].b,&p[i].c);
		sort(p,p+m,cmp);
		int ans=0,sum=0;
		for(i=0; i<m; i++)
		{
			if(find(p[i].a)==find(p[i].b))
				continue;
			merge(p[i].a,p[i].b);
			book[i]=1;//标记最小生成树用过那条边
			ans++;
			sum+=p[i].c;
			if(ans==n-1)
				break;
		}
		printf("%d ",sum);
		int minn=0x3f3f3f;
		for(i=0; i<m; i++)//求次小生成树
		{
			if(book[i])//如果边被用过
			{
				ans=0;
				sum=0;
				init();//一定要初始化
				for(j=0; j<m; j++)
				{
					if(i==j)//跳过这条边
					continue;
					if(find(p[j].a)==find(p[j].b))
						continue;
					merge(p[j].a,p[j].b);
					ans++;
					sum+=p[j].c;
					if(ans==n-1)
					{
						if(sum<minn)//遍历比较找到次小
						minn=sum;
						break;
					}		
				}
			}
		}
		printf("%d\n",minn);	
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值