题目描述
有N个村庄,编号从1到N,你应该建造一些道路,使每个村庄都可以相互连接。
两个村A和B是相连的,当且仅当A和B之间有一条道路,或者存在一个村C使得在A和C之间有一条道路,并且C和B相连。
现在一些村庄之间已经有一些道路,你的任务就是修建一些道路,使所有村庄都连通起来,并且所有道路的长度总和是最小的。
输入
测试数据有多组
第一行是整数N(3 <= N <= 100),代表村庄的数量。 然后是N行,其中第i行包含N个整数,这些N个整数中的第j个是村庄i和村庄j之间的距离(距离是[1,1000]内的整数)。
然后是整数Q(0 <= Q <= N *(N + 1)/ 2),接下来是Q行,每行包含两个整数a和b(1 <= a <b <= N),代表着村庄a和村庄b之间的道路已经建成。
输出
对于每组测试数据
输出一个整数,表示要构建的道路的长度总和最小值
样例输入
3 0 990 692 990 0 179 692 179 0 1 1 2
样例输出
179
#include<iostream>
using namespace std;
struct com {
int fis;
int sec;
int weight;
};
class Graph
{
private:
int** martix, * group;//group存放所在连通图
int n, len; //n 是节点个数 len是边的数
int sum = 0;;
com* sort;//设置排序数组
int* visited;//设置访问节点
int way;
public:
Graph() {};
void SetGraph(int n);
void kruskal();
void show();
void connect();//设置联通函数
};
void Graph::SetGraph(int _n){
int i, j;
n = _n;
way = (n * (n - 1)) / 2;
martix = new int* [n + 1];
group = new int[n + 1];
visited = new int[n + 1];
for (i = 1; i <= n; i++)//输入矩阵
{
martix[i] = new int[n + 1];
group[i] = i;
visited[i] = false;
for (j = 1; j <= n; j++)
{
cin >> martix[i][j];
}
}
connect();
}
void Graph::connect() {//将连接的点村庄置于同一连通图
cin >> len;
for (int i = 1; i <= len; i++)
{
int to1, to2;
cin >> to1 >> to2;
if (group[to2] != group[to1]) {//在不同的连通图时
if (!visited[to2]) {
group[to2] = group[to1];
visited[to2] = true;
visited[to1] = true;
}
else if (visited[to2] && !visited[to1]) {
group[to1] = group[to2];
visited[to1] = true;
}
else if (visited[to2] && visited[to1]) {
int temp = group[to2];
for (int i = 1; i <= n; i++) {//确保所在连通图所有点全部置于同一连通图
if (group[i] == temp)
group[i] = group[to1];
}
}
}
}
}
void Graph::kruskal()
{
sort = new com[way+1];
int fis = -1, sec = -1;
int temp;
for (int i = 0; i <= way; i++) {//sort数组
sort[i].fis = fis;
sort[i].sec = sec;
int temp = 9999;
if (fis != -1) {
sort[i].weight = martix[sec][fis];
martix[sec][fis] = 9999;
}
for (int j = 1; j <= n; j++) {
for (int k = 1; k < j; k++) {
if (temp > martix[j][k]) {
temp = martix[j][k];
fis = k;
sec = j;
}
}
}
}
for (int i = 1; i <= way; i++) {
int fis = sort[i].fis;
int sec = sort[i].sec;
if (group[fis] != group[sec])
{
sum += sort[i].weight;
int temp = group[sec];
for (int i = 1; i <= n; i++) {//确保所在连通图所有点全部置于同一连通图
if (group[i] == temp)
group[i] = group[fis];
}
}
}
}
void Graph::show()
{
cout << sum << endl;
}
int main()
{
int n;
while (cin>>n) {
Graph m;
m.SetGraph(n);
m.kruskal();
m.show();
}
}