题目描述
有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之间的道路已经建成。
输出
对于每组测试数据
输出一个整数,表示要构建的道路的长度总和最小值
输入样例1 | 输出样例1 |
3 0 990 692 990 0 179 692 179 0 1 1 2 | 179 |
提示:样例里的修路记录中有重复的部分,别被假路卡住啦/悲
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
struct node{
int va,vb,weight;
};
class country_road{
int num;
int**st;
public:
country_road(){}
country_road(int n,int **s){
num = n;
st = new int *[num];
for(int i = 0 ; i < num ; i++ ){
st[i] = new int [num];
for(int j = 0 ; j < num ; j++ ){
st[i][j] = s[i][j];
}
}
}
void kruskal(node *r,int r_t);
bool static cmp(node t1,node t2);
};
void country_road::kruskal(node *r,int r_t){
int len = num*(num-1)/2;
int *v = new int [num];
for(int i = 0 ; i < num ; i++ ){
v[i] = i;
}
int del=0;
node *test = new node [len];
for(int i = 0 ,pos = 0; i < num ; i++ ){
for(int j = i+1 ; j < num ; j++ ){
test[pos].va = i;test[pos].vb = j ; test[pos].weight = st[i][j];
if(v[i]!=v[j])
for(int k = 0 ; k < r_t ; k++){
if(r[k].va-1==i&&r[k].vb-1==j){
test[pos].weight = 0;del++;
for(int z = 0 ; z < num ; z++ ){
if(z!=i&&v[z] == v[i]){
v[z] = v[j];
}
}
v[i] = v[j];
break;//*降重*防止旧路记录中有重复记录
}
}
pos++;
}
}
sort(test,test+len,cmp);
int sum=0;
for(int i = 0 ,k = 0; i < len&&k<num-1-del ; i++ ){
if(v[test[i].va]!=v[test[i].vb]){
//省略造图
k++;
sum+=test[i].weight;
for(int j = 0 ; j < num ; j++ ){
if(j!=test[i].va&&v[j] == v[test[i].va]){
v[j] = v[test[i].vb];
}
v[test[i].va]=v[test[i].vb];
}
}
}
cout<<sum;
}
bool country_road::cmp(node t1,node t2){
return t1.weight<t2.weight;
}
int main(){
int t;
int flag =0;
while(cin>>t){
if(flag == 1)
cout<<endl;
flag = 1;
int **s = new int *[t];
for(int i = 0 ; i < t ; i++ ){
s[i] = new int [t];
for(int j = 0 ; j < t ; j++ ){
cin>>s[i][j];
}
}
country_road c_r(t,s);
int q;
cin>>q;
node *r = new node [q];
for(int i = 0 ; i < q ; i++ ){
cin>>r[i].va>>r[i].vb;r[i].weight = s[r[i].va-1][r[i].vb-1];
if(r[i].va>r[i].vb)
swap(r[i].va,r[i].vb);
}
c_r.kruskal(r,q);
}
return 0;
}