(ssl 2346)联络员#kruskal,并查集#

题目

Tyvj的通信渠道分为两大类,一类是必选通信渠道,无论价格多少,你都需要把所有的都选择上;还有一类是选择性的通信渠道,你可以从中挑选一些作为最终管理员联络的通信渠道。数据保证给出的通行渠道可以让所有的管理员联通。


分析

其实求的就是最小生成树
必选的必须得选(这是重点)
所以我们就想到了Kruskal
Prim处理有些麻烦。


代码时间复杂度 O(E*logE)

#include <cstdio>
#include <algorithm>
using namespace std;
struct uni{
	int p,u,v,w;
}e[10001]; int n,m,ans,f[2001];
bool cmp(uni x,uni y){
	if (x.p==2&&y.p==2) return x.w<=y.w;
	return x.p<=y.p;
}
int father(int yu){
	if (f[yu]==yu) return yu; return f[yu]=father(f[yu]);
}
bool un(int xu,int yv){
	int fa=father(xu);//找祖先
	int fb=father(yv);//找祖先
	if (fa!=fb) {f[fb]=fa; return 1;} return 0;//祖先不同返回真,否则返回假
}
int main(){
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) f[i]=i;
	for (int i=1;i<=m;i++) scanf("%d%d%d%d",&e[i].p,&e[i].u,&e[i].v,&e[i].w);
	sort(e+1,e+1+m,cmp);//快排
	for (int i=1;i<=m;i++)
	if (e[i].p==1) ans+=e[i].w,un(e[i].u,e[i].v);//必选
	else if (un(e[i].u,e[i].v)) ans+=e[i].w;//选择性判断祖先是否不同
	printf("%d",ans); return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值