传送门:POJ - 1679
题目描述
Given a connected undirected graph, tell if its minimum spanning tree is unique.
Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V’, E’), with the following properties:
- V’ = V.
- T is connected and acyclic.
Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E’) of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E’.
输入描述
The first line contains a single integer $t$ $(1 <= t <= 20)$, the number of test cases. Each case represents a graph. It begins with a line containing two integers $n$ and $m$ $(1 <= n <= 100)$, the number of nodes and edges. Each of the following m lines contains a triple $(x_i, y_i, w_i)$, indicating that xi and yi are connected by an edge with weight = wi. For any two nodes, there is at most one edge connecting them.
输出描述
For each input, if the MST is unique, print the total cost of it, or otherwise print the string ‘Not Unique!’.
思路分析
题目的意思是:判断最小生成树是否唯一。思路:先生成一条最小树,记录所使用的边,然后再枚举换掉每一个边能否再生成权值相等的树。
样例输入
2
3 3
1 2 1
2 3 2
3 1 3
4 4
1 2 2
2 3 2
3 4 2
4 1 2
样例输出
3
Not Unique!
AC代码
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define ll long long
#define ull unsigned long long
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);cout.tie(0);
const int maxn=1e6+10;
const ll mod=1e9+7;
const int INF = 0x3f3f3f3f;
int n,m,f[10000],vis[10000];
struct node{
int x,y,w;
}s[10000];
int cmp(node a,node b){
return a.w<b.w;
}
int find(int x){
if(f[x]==x)
return x;
else
return f[x]=find(f[x]);
}
void sta(){
for(int i=0;i<=n;i++)
f[i]=i;
}
int main() {
int t;
cin>>t;
while(t--){
cin>>n>>m;
sta();
memset(s,0,sizeof(s));
memset(vis,0,sizeof(vis));
for(int i=0;i<m;i++)
cin>>s[i].x>>s[i].y>>s[i].w;
sort(s,s+m,cmp);
int cnt=0,ans=0,k=0;
for(int i=0;i<m;i++){
int t1=find(s[i].x);
int t2=find(s[i].y);
if(t1!=t2){
f[t2]=t1;
cnt++;
ans+=s[i].w;
vis[k++]=i; //记录已经使用的边
}
if(cnt==n-1)
break;
}
int flag=0;
for(int i=0;i<k;i++){ //枚举去除一条已经使用的边
int num=0,sum=0;
sta();
for(int j=0;j<m;j++){
if(j==vis[i])
continue; //去除该已经使用的边
int t1=find(s[j].x);
int t2=find(s[j].y);
if(t1!=t2){
f[t2]=t1;
num++;
sum+=s[j].w;
}
if(num==n-1&&sum==ans){ //有可能生成不了树,但是sum的值可能与ans相同,所以得两个条件同时判断
flag=1;
break;
}
}
}
if(flag)
cout<<"Not Unique!"<<endl;
else
cout<<ans<<endl;
}
}