下面是题目描述:
【题目描述】
学校有n台计算机,为了方便数据传输,现要将它们用数据线连接起来。两台计算机被连接是指它们有数据线连接。由于计算机所处的位置不同,因此不同的两台计算机的连接费用往往是不同的。
当然,如果将任意两台计算机都用数据线连接,费用将是相当庞大的。为了节省费用,我们采用数据的间接传输手段,即一台计算机可以间接的通过若干台计算机(作为中转)来实现与另一台计算机的连接。
现在由你负责连接这些计算机,任务是使任意两台计算机都连通(不管是直接的或间接的)。
【输入】
第一行为整数n(2≤n≤100),表示计算机的数目。此后的n行,每行n个整数。第x+1行y列的整数表示直接连接第x台计算机和第y台计算机的费用。
【输出】
一个整数,表示最小的连接费用。
思考后可知,连接后费用最小,也就是合并后权值最小,这是一个最小生成树问题,使用并查集和Kruskal算法完成。(在连接的过程中求ans)
不知大家发现没有,输入中第n行第n列一定是0,自己到自己没有权值。
下面是程序代码:
#include<bits/stdc++.h>
using namespace std;
int father[5001],ans=0;
struct point
{
int x,y,v;
};
point a[5001];
int find(int x)//递归找呀找爸爸
{
if(father[x]==x)
return x;
return father[x]=find(father[x]);
}
bool cmp(const point &a,const point &b)//按权值排序
{
return a.v<b.v;
}
int n,m=0,x,k=0;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&x);
if(j>i)
{
m++;
a[m].x=i;
a[m].y=j;
a[m].v=x;
}
}
}
for(int i=1;i<=n;i++)
father[i]=i;//建立并查集,自己当自己爸爸
sort(a+1,a+m+1,cmp);
for(int i=1;i<=m;i++)
{
int fx=find(a[i].x),fy=find(a[i].y);
if(fx!=fy)
{
father[fy]=fx; //连接并查集,fx:“乖儿子,我也是你爸爸!”
ans+=a[i].v;//跟新并查集后累加ans
k++;
}
if(k==n-1) break;//最小生成树的条件:N-1连接成最小生成树
}
printf("%d",ans);
return 0;
}
并查集,不过就是一个儿子(WUSIR)认爸爸,爸爸认儿子的过程(^^)。上定义struct point,也可以纯用数组模拟,就是麻烦很多。类似的题,如还要求出连接方案,再设一个数组存储即可。
蒟蒻第一次写博客,不好或有误请大佬些多多包涵~