地址:
点击打开链接
这个题用到了
克鲁斯卡尔算法(其中包括并查集)
算法很简单,直接能看出这个题是最小生成树就行。
把他一开始就修好的路放在一个集合中,每次加一个边,如果在一个集合里,就下一循环,否则把这个节点加入集合,同时把结果也更新,
#include <iostream>
#include<cstdio>
#include<string.h>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAX 110
#define repf(i,from,to) for(int i =from ; i<=to ; i++)
#define ll long long
int x[MAX];//?
struct node{
int s,e,l;
}a[60000];
int num ;
bool cmp(node a , node b )
{
return a.l<b.l;
}
int Find(int k)
{
if(x[k]!=k)
x[k]=Find(x[k]);
return x[k];
}
int main(){
int n,k,sum,d,xs,xe;
while(~scanf("%d",&n))
{
for(int i = 1 ; i <=MAX ; i++)
{
x[i]= i;
}
k = sum = 0 ;
repf(i,1,n)
repf(j,1,n)
{
scanf("%d",&d);
if(d!=0)
{
a[k].s = i;
a[k].e = j ;
a[k++].l = d ;
}
}
scanf("%d",&d);
while(d--)
{
scanf("%d%d",&xs,&xe);
int fa = Find(xs);
int fb = Find(xe);
if(fa!=fb)
{
x[fa] = fb ;
}
}
sort(a,a+k,cmp);
for(int i = 0 ; i < k ; i ++)
{
int fa = Find(a[i].s);
int fb = Find(a[i].e);
if(fa!=fb)
{
x[fa]=fb;
sum+=a[i].l;
}
}
printf("%d\n",sum);
}
}