题意:
有N个村庄,编号从1到N。现需要在这N个村庄之间修路,使得任何两个村庄之间都可以连通。称A、B两个村庄是连通的,
当且仅当A与B有路直接连接,或者存在村庄C,使得A和C两村庄之间有路连接,且C和B之间有路连接。
已知某些村庄之间已经有路直接连接了,试修建一些路使得所有村庄都是连通的、且修路总长度最短。
以矩阵的形式给出了 两个点之间的距离 然后给定一个p p行 每行两个数 表示 两个村庄的路已修好
题解:
裸的最小生成树板子
只要把已经建好的路的权值设为0即可
代码:
#include<iostream> #include<stdio.h> #include<math.h> #include<algorithm> #include<vector> using namespace std; typedef long long ll; const int maxn = 110; int f[maxn]; int n,cnt,q; struct node { int u,v,w; bool operator < (const node &a)const { return w<a.w; } } edge[maxn*maxn]; int Find(int x) { return x==f[x]?x:f[x]=Find(f[x]); } void add(int u,int v,int w) { edge[cnt].u=u; edge[cnt].v=v; edge[cnt++].w=w; } int kruskal() { int ans=0; for(int i=0; i<=n; i++)f[i]=i; sort(edge,edge+cnt); int sum=0; for(int i=0; i<cnt; i++) { int x=edge[i].u; int y=edge[i].v; int fx=Find(x); int fy=Find(y); if(fx!=fy) { f[fx]=fy; ans+=edge[i].w; sum++; } if(sum==n-1)break; } return ans; } int main() { while(~scanf("%d",&n) && n) { for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) { int x; scanf("%d",&x); add(i,j,x); } int q; scanf("%d",&q); for(int i=1;i<=q;i++) { int a,b; scanf("%d%d",&a,&b); add(a,b,0); } printf("%d\n",kruskal()); } return 0; }