问题描述
求一个连通无向图的最小生成树的代价(图边权值为正整数) 输入
第一行是一个整数 N (1 <= N <= 20) ,表示有多少个图需要计算,以下有 N 个图,第 i 图的第一行是一个整数 M (1 <= M <= 50) ,表示图的顶点数,第 i 图的第 2 行至 1+M 行为一个 M*M 的二维矩阵,其元素 ai,j 表示图的 i 顶点和 j 顶点的连接情况,如果 ai ,j = 0,表示 i 顶点和 j 顶点不相连,如果 ai ,j > 0,表示 i 顶点和 j 顶点的连接权值 输出
样例输入
1
6
0 6 1 5 0 0
6 0 5 0 3 0
1 5 0 5 6 4
5 0 5 0 0 2
0 3 6 0 0 6
0 0 4 2 6 0
样例输出 15 Kruskal 算法
对于一个 N*N 矩阵,先构造 N 个没有连接的顶点,按边权值大小从小到大选择顶点,连接不同的生成树,一条边连接 2 个顶点,那么这两个顶点就在同一颗树上,要保证每次连接的树都是不同的,直到只剩下一颗树为止,假如现有一条边连接了 A,B 两个顶点,另一条连接了 B,C 顶点,那么 A,B,C在同一颗树上, A,C 不能再被边连接,同样, C 顶点连接的其他顶点也不能和 A 相连,那么如何做出这样的判断呢? 算法设计
对边权值从小到大排序,采用链式结构,每个节点存储边连接的左右端点 判断边的加入是否构成了环,如果构成了环,那么这条边的加入是不合理的 代码
#include<iostream>
using namespace std;
struct Node
{
int l;
int r;
int len;
Node *next;
};
void insert(Node *&head,Node *p);
int main()
{
Node *head,*p;
int n,m,x,temp;
int *a;
int i,j;
int sum;
cin>>n;
while(n--)
{
sum = 0;
cin>>m;
a = new int[m+1];
for (i = 1; i <= m; i++)
{
a[i] = i; //各端点自为一组
}
head = new Node;
p = head;
p->next = NULL;
for (i = 1; i <= m; i++)
for (j = 1; j <= m; j++)
{
cin>>x;
if (i > j && x != 0) //对称矩阵
{
p=new Node;
p->l = i;
p->r = j;
p->len = x;
p->next = NULL;
insert(head,p);
}
}
p = head->next;
while (p)
{
if (a[p->l] != a[p->r]) //判断是否为同一组
{
sum += p->len;
temp = a[p->l]; //记录左端点
for(i = 1; i <= m; i++)
if (a[i] == temp) //找到原左端点的值
{
a[i] = a[p->r]; //将左端点的值改为和右端点一致
}
}
p = p->next;
}
cout<<sum<<endl;
}
return 0;
}
void insert(Node *&head,Node *p)
{
Node *q = head;
while(q->next && q->next->len <= p->len) //从头结点开始,大的放后面
{
q = q->next;
}
p->next = q->next;
q->next = p;
}