次小生成樹演算法1.1POJ 1679 The Unique MST
阿新 • • 發佈:2018-12-16
#include<bits/stdc++.h> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int maxn=100+10; const int maxm=100*100+10; struct Edge { int u,v,dist; int id;//原始編號 Edge() {} Edge(int u,int v,int d,int id):u(u),v(v),dist(d),id(id) {} bool operator<(const Edge &rhs)const { return dist <rhs.dist; } }; //結構體1,記錄點及權值和編號; struct Kruskal { int n,m; Edge edges[maxm]; vector<int> E;//儲存最小生成樹上的邊原始序號 int fa[maxn];//並查集相關 int findset(int x) { return fa[x]==-1? x: fa[x]=findset(fa[x]); } void init(int n) { this->n=n; m=0; } void AddEdge(int u,int v,int dist,int id) { edges[m++]=Edge(u,v,dist,id); } int kruskal(int ID) { E.clear(); memset(fa,-1,sizeof(fa)); int sum=0; //最小生成樹權值 int cnt=0; //最小生成樹邊數目 sort(edges,edges+m); for(int i=0; i<m; i++) { if(edges[i].id == ID) continue;//ID邊被刪除 int u=edges[i].u, v=edges[i].v; if(findset(u) != findset(v)) { E.push_back(edges[i].id); fa[findset(u)] = findset(v); sum +=edges[i].dist; if(++cnt>=n-1) break; } } if(cnt<n-1) return -1; return sum; } } KK; //結構體中進行演算法; int main() { int T; scanf("%d",&T); while(T--) { int n,m; scanf("%d%d",&n,&m); KK.init(n); for(int i=0; i<m; i++) { int u,v,d; scanf("%d%d%d",&u,&v,&d); KK.AddEdge(u,v,d,i); } int ans1 = KK.kruskal(-1);//就相當於不刪除邊的情況; int ans2 = 1e9; vector<int> E(KK.E); //儲存原圖最小生成樹上的 for(int i=0; i<E.size(); i++) { int tmp = KK.kruskal(E[i]); if(tmp ==-1) continue; //此時圖不連通,不存在最小生成樹 ans2 = min(ans2,tmp); if(ans2 == ans1) break; } if(ans1==ans2) printf("Not Unique!\n"); else printf("%d\n",ans1); } return 0; }