题目链接:http://poj.org/problem?id=1679

       题意是给了n个点,m条边,问最小生成树是否唯一

       首先我们求一个最小生成树把每条边记录下来,然后我们对这个最小生成树进行删边操作,再删除一条边后,能不能再生成一个权值相同的最小生成树就行了。我刚开始有一个错误的想法,但是感觉是对的...就是我们求一个最小生成树,然后把每条边和他的权值记录下来,然后再去遍历所有边去找没有记录过的边而且权值已经出现过的边,这样的话就不是唯一的最小生成树了。然而这画个图就可以看出来显然是错的,因为会出现不连通的情况。


AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <algorithm>
#define maxn 105
using namespace std;
struct Node{
  int x,y,w;
  bool operator < (const Node &a) const{
    return a.w > w;
  }
}Edge[maxn * maxn];
int pre[maxn],cnt[maxn],num;
int T,n,m,ans;
bool flag;

void init(){
  for(int i=0;i<=n;i++) pre[i] = i;
}

void add(int u,int v,int w){
  Edge[num].x = u;
  Edge[num].y = v;
  Edge[num++].w = w;
}

int Find(int x){
  if(x != pre[x]) pre[x] = Find(pre[x]);
  return pre[x];
}

void Kruskal(){
  ans = 0;
  int xx = 0;
  sort(Edge, Edge + num);
  for(int i=0;i<m;i++){
    int fx = Find(Edge[i].x);
    int fy = Find(Edge[i].y);
    if(fx != fy){
      pre[fy] = fx;
      cnt[xx++] = i;
      ans += Edge[i].w;
    }
  }
  for(int k=0;k<xx;k++){
    init();
    int sum = 0;
    int yy = 0;
    for(int i=0;i<m;i++){
      if(i == cnt[k]) continue;
      int fx = Find(Edge[i].x);
      int fy = Find(Edge[i].y);
      if(fx != fy){
        pre[fy] = fx;
        yy ++;
        sum += Edge[i].w;
      }
    }
    if(yy == n - 1 && sum == ans){
      flag = false;
      return ;
    }
  }
}

int main()
{
  scanf("%d",&T);
  while(T--){
    scanf("%d%d",&n,&m);
    init();
    for(int i=0;i<m;i++){
      int u, v, w;
      scanf("%d%d%d",&u,&v,&w);
      add(u, v, w);
      // add(v, u, w);
    }
    num = 0;
    flag = true;
    Kruskal();
    if(flag) printf("%d\n", ans);
    else puts("Not Unique!");
  }
  return 0;
}