http://acm.hdu.edu.cn/showproblem.php?pid=1102
最小生成树,用kruskal算法(克鲁斯克尔算法)。
步骤:
1.新建图G,G中拥有原图中相同的节点,但没有边
2.将原图中所有的边按权值从小到大排序
3.从权值最小的边开始,如果这条边连接的两个节点于图G中不在同一个连通分量中,则添加这条边到图G中
4.重复3,直至图G中所有的节点都在同一个连通分量中
#include <iostream>
#include <algorithm>
using namespace std;
#define N 105
int map[N][N],root[N];
struct edge_node{
int in,out,weight;
};
edge_node edges[N*N/2];
int findroot(int n){
if (n!=root[n])
root[n]=findroot(root[n]);
return root[n];
}
bool cmp(edge_node a,edge_node b){
return (a.weight<b.weight);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1102in.txt","r",stdin);
#endif
int n,i,j,k,m,path;
while (scanf("%d",&n)!=EOF){
for (i=0;i<n;i++){
root[i]=i;
for (j=0;j<n;j++)
scanf("%d",&map[i][j]);
}
for (i=0,k=0;i<n;i++)
for (j=0;j<i;j++){
edges[k].in=i;
edges[k].out=j;
edges[k].weight=map[i][j];
k++;
}
k=0;
scanf("%d",&m);
while (m--){
scanf("%d%d",&i,&j);
i=findroot(i-1);
j=findroot(j-1);
if (i!=j){
root[i]=j;
k++;
}
}
sort(edges,edges+n*(n-1)/2,cmp); //排序
m=0;
path=0;
while (k<=n-1&&m<(n*(n-1)/2)){ //从小到大依次添加。
i=edges[m].in;
j=edges[m].out;
i=findroot(i);
j=findroot(j);
if (i!=j){
root[i]=j;
k++;
path+=edges[m].weight;
}
m++;
}
printf("%d\n",path);
}
return 0;
}