现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。

输入格式:

输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。

输出格式:

输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出−1,表示需要建设更多公路。

输入样例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3

输出样例:

1
12

思路:

​ 该题为最小生成树问题,一般有两种算法,Prim算法、Kruskal算法。这里边的个数M≤3N,说明边的数量级与结点个数一致,使用Kruskal算法更好。如下采用Kruskal算法

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include<bits/stdc++.h>
using namespace std;
#define N 1005
struct s
{
int v,w;
int cost;
} t[N*N];
int father[N],n,m;
void init(int n)
{
for(int i=0; i<=n; i++)
father[i]=i;
}
int find(int x)
{
if(x!=father[x])
return father[x]=find(father[x]);
return x;
}
bool cmp(s& a1,s& a2)
{
return a1.cost<a2.cost;
}
int Kruskal(int n,int m)//n个顶点,m条边数
{
int cnt=0,summ=0;
for(int i=0; i<m; i++)
{
int a=find(t[i].v);
int b=find(t[i].w);
if(a!=b)
{
father[a]=b;
cnt++;
summ+=t[i].cost;
}
if(cnt==n-1)
break;
}
if(cnt==n-1)
return summ;
return -1;
}
int main()
{
cin>>n>>m;
init(n);
for(int i=0; i<m; i++)
cin>>t[i].v>>t[i].w>>t[i].cost;
sort(t,t+m,cmp);
cout<<Kruskal(n,m);
return 0;
}