第一次接触次小生成树。
思路:先生成mst,存储mst的每一条边,然后枚举删除每一条mst中的边,看是否能找出一课次小生成树的权值和最小生成树的权值相等。
如果相等,则不唯一。
Source Code
Problem: 1679 | User: 64162451 | |
Memory: 300K | Time: 16MS | |
Language: C++ | Result: Accepted |
- Source Code
#include<iostream> #include<algorithm> using namespace std; int n,m; const int N=105; int mat[N][N]; const int inf=99999999; int father[N]; struct Edge { int a,b,c; }edge[N*N]; int mst_edge[N]; bool cmp(Edge &a,Edge &b) { if(a.c<b.c) return true; return false; } int find(int u) { while(father[u]>=0) { u=father[u]; } return u; } void Union(int fa,int fb) { if(father[fa]<father[fb]) { father[fa]=father[fa]+father[fb]; father[fb]=fa; } else { father[fb]=father[fa]+father[fb]; father[fa]=fb; } } void krusk() { memset(father,-1,sizeof(father)); memset(mst_edge,0,sizeof(mst_edge)); sort(edge+1,edge+1+m,cmp); int ans=0; int k=0; for(int i=1;i<=m&&k<n-1;i++) { int a=find(edge[i].a); int b=find(edge[i].b); if(a!=b) { Union(a,b); k++; ans+=edge[i].c; mst_edge[k]=i; } } for(int i=1;i<=n-1;i++) { int ans2=0,k2=0; memset(father,-1,sizeof(father)); for(int j=1;j<=m;j++) { if(j==mst_edge[i]) continue; int a=find(edge[j].a),b=find(edge[j].b); if(a!=b) { Union(a,b); k2++; ans2+=edge[j].c; } } if(k2!=n-1) { continue; } if(ans2==ans) { printf("Not Unique!\n"); return ; } } printf("%d\n",ans); } int main() { int cases; scanf("%d",&cases); while(cases--) { scanf("%d%d",&n,&m); memset(edge,0,sizeof(edge)); for(int i=1;i<=m;i++) { scanf("%d%d%d",&edge[i].a,&edge[i].b,&edge[i].c); } krusk(); } return 0; }