跟之前的继续畅通工程几乎一模一样,只是输入换一下。map[i][j]!=0时,才将其做为一条边,否则不加入。
#include<iostream>
#include<algorithm>
using namespace std;
#define NUM 105
struct points
{
int start;
int end;
int w;
}pos[10005];
int set[NUM];
int map[NUM][NUM];
void init()
{
for(int i=0;i<NUM;++i)
set[i]=i;
}
int find(int x)
{
int r=x;
while(r!=set[r])
r=set[r];
return r;
}
int find2(int x)//带路径压缩的查找(非递归版)
{
int k, j, r;
r = x;
while(r != set[r]) //查找根节点
r = set[r]; //找到根节点,用r记录下
k = x;
while(k != r) //非递归路径压缩操作
{
j = set[k]; //用j暂存set[k]的父节点
set[k] = r; //set[x]指向根节点
k = j; //k移到父节点
}
return r; //返回根节点的值
}
void merge(int x,int y)
{
int a=find2(x);
int b=find2(y);
if(a!=b)
set[a]=b;
return;
}
int cmp(struct points a,struct points b)
{
return a.w < b.w;
}
int main()
{
int n,i,j,m,index,x,y,sum;
freopen("C:\\Documents and Settings\\Administrator\\桌面\\input.txt","r",stdin);
//while(cin>>n&&n!=0){
while(scanf("%d",&n)!=EOF&&n!=0){
index=0;
sum=0;
init();
for(i=1;i<=n;++i){
for(j=1;j<=n;++j){
scanf("%d",&map[i][j]);
}
}
scanf("%d",&m);
while(m--){
scanf("%d%d",&x,&y);
map[x][y]=0;
merge(x,y);
}
for(i=1;i<=n;++i){
for(j=1;j<=n;++j){
if(map[i][j]!=0){
pos[index].start=i;
pos[index].end=j;
pos[index].w=map[i][j];
++index;
}
}
}
sort(pos,pos+index,cmp);
for(i=0;i<index;++i){
if(find2(pos[i].start)!=find2(pos[i].end)){
merge(pos[i].start,pos[i].end);
sum+=pos[i].w;
}
}
printf("%d\n",sum);
}
return 0;
}