图结构练习——最小生成树
Time Limit: 1000MS Memory Limit: 65536KB
Problem Description
有n个城市,其中有些城市之间可以修建公路,修建不同的公路费用是不同的。现在我们想知道,最少花多少钱修公路可以将所有的城市连在一起,使在任意一城市出发,可以到达其他任意的城市。
Input
输入包含多组数据,格式如下。
第一行包括两个整数n m,代表城市个数和可以修建的公路个数。(n <= 100, m <=10000)
剩下m行每行3个正整数a b c,代表城市a 和城市b之间可以修建一条公路,代价为c。
Output
每组输出占一行,仅输出最小花费。
Example Input
3 2
1 2 1
1 3 1
1 0
7 12
1 2 2
1 3 4
1 4 1
2 4 3
2 5 10
3 4 2
3 6 5
4 5 7
4 6 8
4 7 4
5 7 6
6 7 1
8 14
1 2 1
2 3 2
3 5 3
5 6 4
6 7 5
7 8 6
8 1 7
1 4 7
2 4 6
3 4 5
5 4 4
6 4 3
7 4 2
8 4 1
6 7
1 2 1
1 6 1
2 3 1
3 4 1
3 6 1
4 5 1
5 6 1
4 5
1 2 7
1 3 2
1 4 9
2 3 8
3 4 1
Example Output
2
0
16
16
5
10
(附加测试数据4组)prim算法(小树长大)的简单应用,之前在中国大学MOOC上听了浙江大学陈越老师的讲解,感觉实现起来比较困难,还要应用并查集的知识。真正敲代码是发现在判断所找出的边是否构成回路这一难题上,在初始化距离数组dis上便可轻松解决。题目最大的坑点是输入的数据中有可能两城市的建造价格为0,所以之前WA了五次。
AC代码1:
# include <bits/stdc++.h>
using namespace std;
const int MAXN=110;
const int maxx=INT_MAX;
bool collect[MAXN][MAXN];
int Distance[MAXN][MAXN];
int dis[MAXN], parent[MAXN];
int N, M;
int sum;
int zhao()
{
int a=-1, b=maxx;
for(int i=1; i<=N; i++)
{
if(dis[i]!=-1&&dis[i]<b)
{
a=i;
b=dis[i];
}
}
return a;
}
int Find(int a)
{
int i;
for(i=parent[a]; i!=parent[i]; i=parent[i]);
return i;
}
void Prim()
{
dis[1]=-1;
for(int i=2; i<=N; i++)
{
if(collect[i][1])
dis[i]=Distance[i][1];
}
while(1)
{
int m=zhao();
if(m==-1)
break;
while(Find(m)==1)
{
dis[m]=-1;
m=zhao();
}
sum+=dis[m];
dis[m]=-1;///已经在树里的结点dis设置为1,防止与建造费用为0的结点冲突
for(int i=1; i<=N; i++)
{
if(collect[m][i]&&dis[i]!=0)
{
if(dis[i]>Distance[m][i])
{
dis[i]=Distance[m][i];
parent[i]=m;
}
}
}
}
}
void start()
{
for(int i=1; i<=N; i++)
{
for(int j=1; j<=N; j++)
Distance[i][j]=maxx;
}
for(int i=1; i<=N; i++)
dis[i]=maxx;
for(int i=1; i<=N; i++)
parent[i]=i;
}
int main()
{
while(cin>>N>>M)
{
memset(collect,false,sizeof(collect));
memset(parent,0,sizeof(parent));
start();
sum=0;
while(M--)
{
int a, b, c;
cin>>a>>b>>c;
if(Distance[a][b]>c)
{
collect[a][b]=true;
collect[b][a]=true;
Distance[a][b]=c;
Distance[b][a]=c;
}
}
Prim();
cout<<sum<<endl;
}
return 0;
}
AC代码2:
# include <bits/stdc++.h>
using namespace std;
const int MAXN=110;
const int maxx=INT_MAX;
int Distance[MAXN][MAXN];
int dis[MAXN];
int N, M;
int sum;
int zhao()
{
int a=-1, b=maxx;
for(int i=1; i<=N; i++)
{
if(dis[i]!=-1&&dis[i]<b)
{
a=i;
b=dis[i];
}
}
return a;
}
void Prim()
{
dis[1]=-1;
for(int i=2; i<=N; i++)
dis[i]=Distance[1][i];
for(int j=1; j<N; j++)
{
int m=zhao();
sum+=dis[m];
dis[m]=-1;
for(int i=1; i<=N; i++)
{
if(dis[i]!=-1&&dis[i]>Distance[m][i])
dis[i]=Distance[m][i];
}
}
}
void start()
{
for(int i=1; i<=N; i++)
{
for(int j=1; j<=N; j++)
{
if(i==j)
Distance[i][j]=0;
else
Distance[i][j]=maxx;
}
}
}
int main()
{
while(cin>>N>>M)
{
start();
sum=0;
while(M--)
{
int a, b, c;
cin>>a>>b>>c;
if(Distance[a][b]>c)
{
Distance[a][b]=c;
Distance[b][a]=c;
}
}
Prim();
cout<<sum<<endl;
}
return 0;
}