hdu 1232 点击打开链接
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#include<iostream>
using namespace std;
bool t[1050];
int pre[1050];
int find(int x)//找到一个集合父节点
{
int r=x;
while(pre[r]!=r)
r=pre[r];
int i=x,j;
while(pre[i]!=r){
//路径压缩,缩小寻找次数 /进行这个循环是为了将路径上所有的点的根节点置为 X (这一段while循环我刚开始没明白,加这一段的原因是优化运算速度吧,感觉这样比递归要快)
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
void mix(int x,int y)//将两个元素连接起来
{
int fx=find(x);
int fy=find(y);
if(fx!=fy)
pre[fy]=fx;
}
int main()
{
int m,n,a,b,ans;
while(scanf("%d%d",&n,&m)&&n)
{
for(int i=1; i<=n; i++)pre[i]=i;
for(int i=1; i<=m; i++)
{
scanf("%d%d",&a,&b);
mix(a,b);
}
mem(t,0);
for(int i=1; i<=n; i++)
t[find(i)]=1;//标记根节点
int i,ans=0;
for(i=1; i<=n; i++)
if(t[i])
ans++;
printf("%d\n",ans-1);//因为题意是使所有元素在一个根节点上,所以输出ans-1
}
return 0;
}
void init()//初始化函数
{
int i;
for(i = 1; i <= n; i ++)
f[i] = i;
return;
}
int find(int v)//查找根结点
{
if(f[v] == v)
return v;
else
{
//这里是路径压缩,每次在函数返回时,把遇到的结点改为根结点的编号
//提高找到根结点的速度
f[v] = find(f[v]);
return f[v];
}
}
void merge(int x,int y)//合并两个子集的函数
{
int t1,t2;
t1 = find(x);
t2 = find(y);
if(t1 != t2)
{
f[t1] = t2;
}
return;
}
hdu 1233 点击打开链接
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int pre[100001];
struct road{
int x,y,z;
}a[100001];
bool cmp(struct road q,struct road w){
return q.z<w.z;
}
int findl(int x){
int r=x;
while(pre[r]!=r){
r=pre[r];
}
int i=x,j;
while(pre[i]!=r){
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
int merge1(int x,int y){
int i=findl(x),j=findl(y);
if(i!=j){
pre[j]=i;
return 1;
}
return 0;
}
int main(){
int n,m;
while(cin>>n&&n){
m=n*(n-1)/2;
int j;
for(j=1;j<=n;j++) pre[j]=j;
for(j=1;j<=m;j++){
cin>>a[j].x>>a[j].y>>a[j].z;
}
int sum=0,s=0;
sort(a+1,a+1+m,cmp);
for(j=1;j<=m;j++){
if(merge1(a[j].x,a[j].y)){
sum++;
s+=a[j].z;
}
if(sum==n-1) break;
}
cout<<s<<endl;
}
}