题目大意:输入一个整数n,表示村庄的数目。在接下来的n行中,每行有n列,表示村庄i到村庄 j 的距离。(下面会结合样例说明)。接着,输入一个整数q,表示已经有q条路修好。
在接下来的q行中,会给出修好的路的起始村庄和结束村庄。。
输入样例说明如下:
解题思路:最小生成树(kruscal算法)
1)以前的题会直接给村庄编号以及村庄距离。而这道题,这是给出村庄的距离矩阵。村庄的编号信息蕴含在
矩阵中。这时候的读取方法为:
for(i = 1 ; i <= n ; ++i){ for(j = i + 1 ; j <= n ; ++j){ e[count].begin = i; e[count].end = j; e[count].weight = map[i][j]; count++; } }
2)点的起始编号与变得起始编号没有必然的联系。即点可以从1开始计数,而边则从0开始计数。
for( i = 1 ; i < maxn ; ++i){ father[i] = i; } for( i = 0 ; i < count ; ++i){ int fx = find(e[i].begin); int fy = find(e[i].end); if(fx != fy){ father[fx] = fy; sum += e[i].weight; } }
3)已修的路,令weight为0即可。
代码如下:
/* * 1102_1.cpp * * Created on: 2013年8月26日 * Author: Administrator */ #include <iostream> using namespace std; struct edge{ int begin; int end; int weight; }; const int maxn = 6000; int father[maxn]; edge e[maxn*maxn]; int find(int x){ if( x == father[x]){ return x; } father[x] = find(father[x]); return father[x]; } int kruscal(int count){ int i; int sum = 0; for( i = 1 ; i < maxn ; ++i){ father[i] = i; } for( i = 0 ; i < count ; ++i){ int fx = find(e[i].begin); int fy = find(e[i].end); if(fx != fy){ father[fx] = fy; sum += e[i].weight; } } return sum; } bool compare(const edge& a , const edge& b){ return a.weight < b.weight; } int main(){ int n; while(scanf("%d",&n)!=EOF){ int i,j; int map[n+1][n+1]; for( i = 1 ; i <= n ; ++i){ for( j = 1 ; j <= n ; ++j){ scanf("%d",&map[i][j]); } } int q; scanf("%d",&q); for( i = 1 ; i <= q ; ++i){ int a ,b; scanf("%d%d",&a,&b); map[a][b] = 0; } int count = 0; for(i = 1 ; i <= n ; ++i){ for(j = i + 1 ; j <= n ; ++j){ e[count].begin = i; e[count].end = j; e[count].weight = map[i][j]; count++; } } sort(e, e + count , compare); int sum = kruscal(count); printf("%d ",sum); } }