题意:给定N个村庄,及其连通情况,建造最少的路,使村庄全部连通,其中AB若连通,则AB之间有路或AC,CB之间有路
解题思路:调用kruskal算法,求最小生成树的最小权值和
感想:刚学完的数据结构,看到题还是不会写,就又去翻了下课本学习了一下,手敲了一个例子,算是加深了对数据结构的理解
源码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=110;
struct Edge{
int u,v;
int cap;
}edge[N*N];
int n,cnt,ans;
int father[N],rank[N];
void addedge(int cu,int cv,int cw){
edge[cnt].u=cu; edge[cnt].v=cv; edge[cnt].cap=cw;
cnt++;
}
void makeSet(){
for(int i=1;i<=n;i++){
father[i]=i;
rank[i]=1;
}
}
int findSet(int x){
if(x!=father[x]){
father[x]=findSet(father[x]);
}
return father[x];
}
int cmp(Edge a,Edge b){
return a.cap<b.cap;
}
void Kruskal(){
sort(edge,edge+cnt,cmp);
for(int i=0;i<cnt;i++){
int fx=findSet(edge[i].u);
int fy=findSet(edge[i].v);
if(fx==fy)
continue;
ans+=edge[i].cap;
if(rank[fx]>=rank[fy]){
father[fy]=fx;
rank[fx]+=rank[fy];
}else{
father[fx]=fy;
rank[fy]+=rank[fx];
}
}
}
int main(){
while(~scanf("%d",&n)){
makeSet();
cnt=0;
int w;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
scanf("%d",&w);
addedge(i,j,w);
}
int q,u,v;
scanf("%d",&q);
while(q--){
scanf("%d%d",&u,&v);
int fx=findSet(u);
int fy=findSet(v);
if(rank[fx]>=rank[fy]){
father[fy]=fx;
rank[fx]+=rank[fy];
}else{
father[fx]=fy;
rank[fy]+=rank[fx];
}
}
ans=0;
Kruskal();
printf("%d\n",ans);
}
return 0;
}