F - Agri-Net (最小生成树&kruskal)
思路:板子题。(第一次学这个算法标记一下)。思路就是对边排序,取n-1条边生成一棵权值和最小的树。生成树的过程用并查集实现。
AC代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int N=1e2+5;
int n,s[N];
struct edge{
int u,v,w;
bool operator<(const edge&a)const{ //重载'<'
return w<a.w;
}
}now;
vector<edge>e;
int find(int x){
if(s[x]!=x) s[x]=find(s[x]);
return s[x];
}
int kruskal(){
int ans=0;
for(int i=1;i<=n;i++) s[i]=i;
sort(e.begin(),e.end());//排序
int tot=0;
for(int i=0;i<e.size();i++){
int fa=find(e[i].u),fb=find(e[i].v);
if(fa==fb) continue;//防止生成环.
tot++;
s[fb]=fa;
ans+=e[i].w;
if(tot==n-1) break; //n-1条边生成一棵树.
}
return ans;
}
int main(){
while(~scanf("%d",&n)){
e.clear();//初始化
for(int i=1;i<=n;i++)
for(int j=1,w;j<=n;j++)
{
scanf("%d",&w);
if(i>j) e.push_back({i,j,w});//防止重边
}
printf("%d\n",kruskal());
}
return 0;
}