题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1879
心得:本来以为可以水一发,结果发现自己wa到怀疑人生, 在写Kruskal的时候我直接用pre[x]!=pre[y]来判断,一直wrong,最后想了一下,判断是否在一个集合里,只能用find找,所以就可以在join函数里加上一发判断。
题目:坑点,要用scanf输入,否则会超时,然后flag为1的情况下,value置为1。
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const int maxn=10100;//这个地方开小了,根据题意用该是平房
int N;
struct node{
int from;
int to;
int value;
}p[maxn];
bool cmp(node a,node b)
{
return a.value<b.value;
}
int pre[maxn];
void buildset(int size)
{
for(int i=0;i<=size;i++) pre[i]=i;
}
int find(int x)
{
int p,tmp;
p=x;
while(x!=pre[x]) x=pre[x];
while(p!=x){
tmp=pre[p];
pre[p]=x;
p=tmp;
}
return x;
}
bool join(int x,int y)//join函数充当判断是否在一个集合内
{
int p=find(x);
int q=find(y);
if(p!=q){
pre[p]=q;
return true;
}
return false;
}
void kru(int n)
{
sort(p,p+n,cmp);//数组从那个地方开始
int sum=0;
int count=0;
for(int i=0;i<n;i++){
if(join(pre[p[i].from],pre[p[i].to])){
sum+=p[i].value;
count++;
}
if(count==N-1) break;//最小生成树,边数等于点数减一
}
printf("%d\n",sum);
}
int main()
{
int n;while(scanf("%d",&n),n){
N=n;//指的是点的个数
buildset(n);
for(int i=0;i<n*(n-1)/2;i++){
int flag;
scanf("%d%d%d%d",&p[i].from,&p[i].to,&p[i].value,&flag);//cin>>p[i].from>>p[i].to>>p[i].value>>flag;
if(flag) p[i].value=0;
}
kru(n*(n-1)/2);//一开始用的n,越界
}
}