0
点赞
收藏
分享

微信扫一扫

最小生成树练习3


​​畅通道路​​放图祭命运共同体

最小生成树练习3_hdu


祭祀完毕!

下面来看这道题。

这输入方式……不明摆着让我们用kruscal吗?

只是这道题与之前两道不一样的地方是,有部分道路是事先修好的。

那么我们就稍微变通一下即可。

我们回想一下,我们怎么记录生成树的?并查集!

所以我们只需要在读入时,把现成的边在并查集中连在一起即可,剩下的这个边就可以直接扔掉,不需要放在kruscal的排序序列中。剩下的按kruscal做一遍即可。

每加一条边,把边权加在最终结果即可。

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct edge{
int u,v,w;
};

int cmp(edge a,edge b){
return a.w<b.w;
}
int n,m;
edge e[10005];
int p[105];
int ans;
int find(int cur){
return cur==p[cur]?cur:p[cur]=find(p[cur]);
}
void work(){
ans=0;
sort(e,e+m,cmp);
for(int i=0;i<m;i++){
int x=find(e[i].u),y=find(e[i].v);
if(x!=y){
p[x]=y;
ans+=e[i].w;
}
}
}

int main(){
while(1){
scanf("%d",&n);
if(n==0){
break;
}
for(int i=1;i<=n;i++){
p[i]=i;
}
m=0;
for(int i=0;i<n*(n-1)/2;i++){
int u,v,w,vis;
scanf("%d%d%d%d",&u,&v,&w,&vis);
if(vis){
p[find(u)]=find(v);
}else{
e[m].u=u;
e[m].v=v;
e[m].w=w;
m++;
}
}
work();
printf("%d\n",ans);
}
return 0;
}

PS:这两天在忙着填志愿,可能做题比较少,以后会加大题量的。


举报

相关推荐

0 条评论