题意:
有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;
}
知识兔kruskal