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

ACM Contest and Blackout

vjudge提交链接

题意:
——求最小生成树和次最小生成树,一定存在。

t组样例
n,m分别代表n个城镇,m条双向边
下面m行边的信息。

解题思路:
并查集版: 最小生成树和次最小生成树模板

——如何求:次最小生成树

  1. 求出最小生成树,标记用了哪些边,
  2. 被标记的n-1条边每次只有一个不用,再求最小生成树,
  3. 会得到(n-1)个最小生成树的值,最小的一定是次最小生成树的值。

——为什么。

  1. 第一次求最小生成树,被标记的边一定都是最优的,
  2. 如果有一条边不用,再求最小生成树,得到的一定是次最小生成树
  3. 但去掉哪条边合适呢,不清楚,需要模拟出所有情况,找最小。

代码:Krusk

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=110;
int f[N],book[N*N/2];
int n,m;
struct Node{
	int u,v,w;
}q[N*N/2];
bool cmp(Node a,Node b)
{
	return a.w<b.w;
}
void init()
{
	for(int i=1;i<=n;i++)
		f[i]=i;
}
int find(int x)
{
	if(x!=f[x])
		f[x]=find(f[x]);
	return f[x];
}
int Merge(int u,int v)
{
	int tu=find(u);
	int tv=find(v);
	if(tu!=tv)
	{
		f[tv]=tu;
		return 1;
	}
	return 0;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d %d",&n,&m);
		for(int i=1;i<=m;i++)
			scanf("%d %d %d",&q[i].u,&q[i].v,&q[i].w);
		sort(q+1,q+1+m,cmp);
		init();
		memset(book,0,sizeof(book));
		int cnt1=0,sum=0;
		for(int i=1;i<=m;i++)
		{
			if(Merge(q[i].u,q[i].v)==1)
			{
				book[i]=1;
				sum+=q[i].w;
				cnt1++;
				if(cnt1==n-1)
					break;
			}
		}
		int mind=sum;
		int Cmind=INF;
		for(int i=1;i<=m;i++)
		{
			if(book[i]==1)
			{
				init();
				sum=0;cnt1=0;
				for(int j=1;j<=m;j++)
				{
					if(i==j)	continue;
					if(Merge(q[j].u,q[j].v)==1)
					{
						sum+=q[j].w;
						cnt1++;
						if(cnt1==n-1)
						{
							Cmind=min(Cmind,sum);
							break;
						}	
					}
				}
			}
		}
		printf("%d %d\n",mind,Cmind);
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值