HDU3367:最大生成树

HDU3367

题意:这一题题目有点绕,这里不是简单地找最大生成树,这课树还可以最多有一个环。然后我们要找出这么多树构成的最大森林。题解在代码中给出了。

代码:

/*

从大到小排序边
1、如果根结点相同,如果没有环,就合并,并标记有环。
2、如果根结点相同,有环了,就不合并。
3、如果根结点不同,如果两边多有环,就不合并。
4、如果根结点不同,两边只有一个环,那就合并,打上标记。
5、如果根节点不同,两边都没有换,就直接合并。
每次合并就根新最大时。
*/
include <bits/stdc++.h>
using namespace std;
int const N = 10000 + 10;
int const M = 100000 + 10;
int const inf = 0x7f7f7f7f;
int n,m,fa[N],vis[N];
int find(int x){
	return fa[x] == x ? x : (fa[x] = find(fa[x]));
}
struct Edge
{
	int u,v,w;
}p[M];
bool cmp(Edge a,Edge b){
	return a.w > b.w;
}
int Kruskal(){
	int ans = 0;
	sort(p,p+m,cmp);
	for(int i=0;i<n;i++)	fa[i] = i,vis[i] = false;
	for(int i=0;i<m;i++){
		int x = find(p[i].u),	y = find(p[i].v);
		if(x == y){   //如果根结点相同,如果没有环,就合并,并标记有环。
			if(!vis[y]){
				fa[x] = y;
				ans += p[i].w;
				vis[y] = vis[x] = true;
			}
		}else{    //如果根结点不同,
			if(vis[x]&&vis[y])	continue;   //其中两个都有环,就不合并
			if(vis[x]||vis[y])	vis[y] = vis[x] = true;  //一个有环,打上标记合并
			fa[x] = y;
			ans += p[i].w;
		}
	}
	return ans;
}
int main(){
	while(~scanf("%d%d",&n,&m)){   //注意不只一个连通图
		if(!n && !m)	return 0;
		for(int i=0;i<m;i++){
			int x,y,d;
			scanf("%d%d%d",&x,&y,&d);
			p[i] = (Edge){x,y,d};
		}
		printf("%d\n",Kruskal());
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值