D. 道路建设 (Ver. I)
题目描述
有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>
#include <string>
#include <queue>
using namespace std;
class Graph{
int vexNum;//顶点数
int arcNum;//边数
int **array;//邻接矩阵
bool *visit;//访问标志
int Index(string str);
bool isOver();//判断是否访问完全 完成即结束
public:
Graph(int num);
~Graph();
void Prim();
};
//根据输入创建无向图
Graph::Graph(int num){
vexNum=num;//顶点数
array = new int*[vexNum];
visit = new bool[vexNum];
for(int i=0;i<vexNum;i++)
{
visit[i] = 0;
array[i] = new int[vexNum];
for(int j=0;j<vexNum;j++)
array[i][j] = 9999;//邻接矩阵
}
for(int i=0;i<vexNum;i++)
{
int weight[vexNum];
for(int s=0;s<vexNum;s++)
cin>>weight[s];
for(int j=0;j<vexNum;j++)
{
array[i][j]=weight[j];
}
}
int n;
cin>>n;
while(n--)
{
int a,b;
cin>>a>>b;
array[a-1][b-1]=0;
array[b-1][a-1]=0;
}
}
Graph::~Graph() {
}
void Graph::Prim() {
int v = 0;
visit[v]=1;
int minWeight=0;
while (!isOver())
{
int min=9999,startVex=-1,endVex=-1;
for(int i=0;i<vexNum;i++)
{
if(visit[i])//从已访问中的开始查找
{
for(int j=0;j<vexNum;j++)
{
if(!visit[j] && array[i][j]<min) {
min = array[i][j];
startVex = i;
endVex = j;
}//找最小权值边
}
}
}
visit[endVex] = 1;
minWeight+=min;
}
cout<<minWeight<<endl;
}
bool Graph::isOver() {
for(int i=0;i<vexNum;i++)
if(!visit[i])
return false;
return true;
}
int main()
{
int num;
while(cin>>num)
{
Graph myGraph(num);
myGraph.Prim();
}
return 0;
}