题目
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;
}