圖結構練習——最小生成樹
Time Limit: 1000MS Memory limit: 65536K
題目描述
有n個城市,其中有些城市之間可以修建公路,修建不同的公路費用是不同的。現在我們想知道,最少花多少錢修公路可以將所有的城市連在一起,使在任意一城市出發,可以到達其他任意的城市。
輸入
輸入包含多組數據,格式如下。
第一行包括兩個整數n m,代表城市個數和可以修建的公路個數。(n <= 100, m <=10000)
剩下m行每行3個正整數a b c,代表城市a 和城市b之間可以修建一條公路,代價爲c。
輸出
每組輸出佔一行,僅輸出最小花費。
示例輸入
示例輸出
提示
克魯斯卡爾算法,找最小的邊,不形成環路即可,找到n-1條邊,就是最小的生成樹
來源
趙利強
示例程序
<pre name="code" class="cpp">#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct node
{
int a,b,c;
} e[10200],t;
int pre[3050];
int n;
void qs(int l,int r)
{
int i,j;
struct node x;
if(l>=r) return;
i=l;
j=r;
x=e[l];
while(i<j)
{
while(i<j&&e[j].c>=x.c)
j--;
e[i]=e[j];
while(i<j&&e[i].c<=x.c)
i++;
e[j]=e[i];
}
e[i]=x;
qs(l,i-1);
qs(i+1,r);
}
int find(int x)
{
int r=x;
while(pre[r]!=r)
r=pre[r];
return r;
}
int check(int x,int y)
{
int a,b;
a=find(x);
b=find(y);
if(a!=b)
{
pre[a]=b;
return 1;
}
return 0;
}
int Kruskal(int m)
{
int count,sum;
count=sum=0;
int i;
for(i=1; i<=m; i++)
{
if(check(e[i].a,e[i].b))
{
count++;
sum+=e[i].c;
}
if(count==n-1)
break;
}
if(count!=n-1)
return -1;
return sum;
}
int main()
{
int m,i;
while(~scanf("%d%d",&n,&m))
{
for(i=1; i<=m; i++)
{
scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
}
qs(1,m);
for(i=1; i<=n; i++)
pre[i]=i;
int l=Kruskal(m);
printf("%d\n",l);
}
}