题目信息
用避圈法求无向图G的最小生成树
输入:
正整数N M,N代表无向图G的阶数;M代表边数。
随后的M行对应M条边,每行给出3个正整数,分别是该边关联的两个顶点以及该边的权值(假设所有顶点从1到N编号,所有边的权值都不同)。
输出:
用避圈法生成最小生成树过程中选择的边序列,并输出最小生成树的权值。
若G没有生成树,则输出-1.
测试样例
测试样例1
3 3
1 2 1
1 3 2
2 3 3
1 2
1 3
3
测试样例2
1 0
0
解答
#include <iostream>
#include<algorithm>
using namespace std;
int N, M;
struct node
{
int x;
int y;
int cost;
};
struct Rule
{
bool operator()(const node &A, const node &B) const
{
return A.cost < B.cost;
}
};
node road[1000];
int tree[1000];
node roadans[1000];
int find(int t)
{//来查找每个点的开头节点
if (tree[t] == t)
{//自己就是自己的开头说明还没有用过
return t;
}
else
{//递归下去去找开头的节点
return tree[t] = find(tree[t]);
}
}
bool judge(int x, int y)
{//判断是否成环,不成环则返回1
int a = find(x);
int b = find(y);
if (a != b)
{//ab点的开头节点不在一起
tree[a] = b;//那么将a的开头设置为b
return true;
}
else
{
return false;
}
}
void kruskal()
{
int side = 0;//选出的边数
int sumcost = 0;//总开销
for (int i = 0; i < N; i++)
{//每个人的开头都是自己
tree[i] = i;
}
sort(road, road + M, Rule());
for (int i = 0; i < M; i++)
{
if (judge(road[i].x, road[i].y))
{
roadans[side].x = road[i].x;
roadans[side].y = road[i].y;
side++;
sumcost += road[i].cost;
}
if (side == N - 1)
{//已经选够了
break;
}
}
if (side != N - 1)
{//选不出n-1条边,则无法构成最小生成树
cout << "-1" << endl;
}
else
{
for (int i = 0; i < side; i++)
{
cout << roadans[i].x << " " << roadans[i].y << endl;
}
cout << sumcost << endl;
}
}
int main()
{
freopen("E://test.txt", "r", stdin);
cin >> N >> M;
for (int i = 0; i < M; i++)
{
cin >> road[i].x >> road[i].y >> road[i].cost;
}
if (N == 1)
{
cout << "0 " << endl;
}
else
{
kruskal();
}
return 0;
}