洛谷 P1546 最短网络 Agri-Net(最小生成树)
题目链接
https://www.luogu.org/problemnew/show/P1546
说过了不复制内容了
显然是个最小生成树。
解题思路
- prim算法
- Kruskal算法
prim算法很直接,没什么好讲的,直接存图跑一边即可。
重点是Kruskal:
难点在于存图!!
题目给的是一个邻接矩阵,而Kruskal算法是不需要建图的,所以我们需要处理一下。我们考虑哪些边可以不记录:
- 自己和自己之间的边
- 重复的边(去掉a[i][j]或者a[j][i])
怎样实现2呢?当i<j或者i>j时存边即可。
附上代码:
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 struct edge{ 5 int qidian; 6 int zhongdian; 7 int value; 8 }bian[10005]; 9 int fa[105],n,ans,cnt; 10 bool cmp(edge a,edge b){ 11 return a.value<b.value; 12 } 13 int find(int x){ 14 if(fa[x]==x) return x; 15 return fa[x]=find(fa[x]); 16 } 17 int main() 18 { 19 cin>>n; 20 for(int i=1;i<=n;i++) fa[i]=i; 21 for(int i=1;i<=n;i++) 22 for(int j=1;j<=n;j++){ //难点:建边 23 int x; 24 cin>>x; 25 if(i<j){ 26 bian[++cnt].qidian=i; 27 bian[cnt].zhongdian=j; 28 bian[cnt].value=x; 29 } 30 } 31 sort(bian+1,bian+cnt+1,cmp); 32 for(int i=1;i<=cnt;i++){ 33 int p1=bian[i].qidian,p2=bian[i].zhongdian; 34 int f1=find(p1),f2=find(p2); 35 if(f1!=f2){ 36 ans+=bian[i].value; 37 fa[f1]=f2; 38 } 39 } 40 cout<<ans; 41 return 0; 42 }