zoukankan      html  css  js  c++  java
  • POJ 1679 The Unique MST

    题意:给一个图,判断它的最小生成树唯一不唯一。

    解法:首先,容易想到一个O(n^3)或者说O(m*n^2)的方法。就是首先,求一遍最小生成树,记权值和为x1,然后枚举最小生成树中的每一条边,在不用该边的情况下求出的最小生成树权值和为x2,若枚举到某条边的时候x1 = x2,则最小生成树不唯一。若全不相等,则唯一。

       但是,觉得这个方法太慢了,上网搜索了一下搜到了这篇文章,https://www.byvoid.com/blog/2-sp-mst,求次小生成树。(这道题相当于判定最小生成树和次小生成树权值和是否相等)

       上面那篇文章的方法,中心思想在于:枚举每条不在最小生成树中的边,若将它加入最小生成树,一定会生成环,去掉环中的最长边,则是新的最小生成树,若去掉的边权值和加入的边权值相同,则最小生成树和次小生成树权值和相同。当然,这样写的话,时间复杂度也可能打到O(n^3),但是,基于这个思想,能有O(n^2 + m)的写法。

       O(n^2+m)的写法为,从每个节点i遍历整个最小生成树,定义f[j]为最小生成树上从i到j的边中权值最大边的权值,然后遍历所有不在最小生成树中的边(i, k)比较w(i, k)和f[k]的大小,若相等则最小生成树不唯一。

    tag:MST,次小生成树

    解法一O(n^3):

     1 /*
     2  * Author:  Plumrain
     3  * Created Time:  2013-12-03 21:27
     4  * File Name: G-POJ-1679.cpp
     5  */
     6 #include <iostream>
     7 #include <cstdio>
     8 #include <cstring>
     9 #include <algorithm>
    10 
    11 using namespace std;
    12 
    13 #define CLR(x) memset(x, 0, sizeof(x))
    14 struct Pat{
    15     int s, e, w;
    16 };
    17 
    18 int n, m, f[10005];
    19 bool v[10005];
    20 Pat p[10005];
    21 
    22 bool cmp(Pat a, Pat b)
    23 {
    24     return a.w < b.w;
    25 }
    26 
    27 void init()
    28 {
    29     scanf ("%d%d", &n, &m);
    30     for (int i = 0; i < m; ++ i)
    31         scanf ("%d%d%d", &p[i].s, &p[i].e, &p[i].w);
    32     sort (p, p+m, cmp);
    33     CLR (v);
    34 }
    35 
    36 int find(int x)
    37 {
    38     if (x != f[x]) f[x] = find(f[x]);
    39     return f[x];
    40 }
    41 
    42 int kruskal(int x)
    43 {
    44     for (int i = 0; i < n; ++ i)
    45         f[i] = i;
    46 
    47     int cost = 0;
    48     for (int i = 0; i < m; ++ i) if (i != x){
    49         int t1 = find(p[i].s), t2 = find(p[i].e);
    50         if (t1 != t2){
    51             cost += p[i].w;
    52             f[t1] = t2;
    53             if (x == -1) v[i] = 1;
    54         }
    55     }
    56 
    57     int tmp;
    58     for (int i = 0; i < n; ++ i){
    59         if (!i) tmp = find(i);
    60         else if (tmp != find(i)) return -1;
    61     }
    62     
    63     return cost;
    64 }
    65 
    66 int main()
    67 {
    68     int T;
    69     scanf ("%d", &T);
    70     while (T--){
    71         init();
    72         int ans = kruskal(-1);
    73         bool ok = 1;
    74         for (int i = 0; i < m; ++ i) if (v[i]){
    75             int tmp = kruskal(i);
    76             if (tmp == ans){
    77                 ok = 0;
    78                 break;
    79             }
    80         }
    81         if (ok) printf ("%d
    ", max(ans, 0));
    82         else printf ("Not Unique!
    ");
    83     }
    84     return 0;
    85 }
    View Code

    解法二O(n^2+m):

      1 /*
      2  * Author:  Plumrain
      3  * Created Time:  2013-12-04 19:35
      4  * File Name: G-POJ-1679-2.cpp
      5  */
      6 #include <iostream>
      7 #include <cstdio>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <vector>
     11 
     12 using namespace std;
     13 
     14 #define CLR(x) memset(x, 0, sizeof(x))
     15 #define CLR1(x) memset(x, -1, sizeof(x))
     16 #define PB push_back
     17 
     18 struct Pat{
     19     int s, e, w;
     20 };
     21 
     22 int n, m;
     23 Pat p[10005];
     24 bool vis[105][105];
     25 int d[105][105], f[105];
     26 int cnt[105];
     27 vector<int> nod[105];
     28 
     29 bool cmp(Pat a, Pat b)
     30 {
     31     return a.w < b.w;
     32 }
     33 
     34 void init()
     35 { 
     36     CLR (vis);
     37     CLR1 (d);
     38 
     39     scanf ("%d%d", &n, &m);
     40     for (int i = 0; i < m; ++ i){
     41         scanf ("%d%d%d", &p[i].s, &p[i].e, &p[i].w);
     42         -- p[i].s; -- p[i].e;
     43         d[p[i].s][p[i].e] = p[i].w;
     44         d[p[i].e][p[i].s] = p[i].w;
     45     }
     46     sort (p, p+m, cmp);
     47 
     48     for (int i = 0; i < n; ++ i)
     49         nod[i].clear();
     50 }
     51 
     52 int find(int x)
     53 {
     54     if (x != f[x]) f[x] = find(f[x]);
     55     return f[x];
     56 }
     57 
     58 int kruskal()
     59 {
     60     for (int i = 0; i < n; ++ i)
     61         f[i] = i;
     62     
     63     int cost = 0;
     64     for (int i = 0; i < m; ++ i){
     65         int s = p[i].s, e = p[i].e, w = p[i].w;
     66         int t1 = find(s), t2 = find(e);
     67         if (t1 != t2){
     68             f[t1] = t2;
     69             cost += w;
     70             nod[s].PB (e);
     71             nod[e].PB (s);
     72             vis[e][s] = vis[s][e] = 1;
     73         }
     74     }
     75 
     76     int tmp;
     77     for (int i = 0; i < n; ++ i){
     78         if (!i) tmp = find(i);
     79         else if (tmp != find(i)) return -1;
     80     }
     81     return cost;
     82 }
     83 
     84 void dfs(int x, int ma)
     85 {
     86     if (cnt[x] != -1) return;
     87 
     88     cnt[x] = ma;
     89     int sz = nod[x].size();
     90     for (int i = 0; i < sz; ++ i)
     91         if (cnt[nod[x][i]] == -1) 
     92             dfs (nod[x][i], max(d[x][nod[x][i]], ma));
     93 }
     94     
     95 int main()
     96 {
     97     int T;
     98     scanf ("%d", &T);
     99     while (T--){
    100         init();
    101         int ans = kruskal();
    102         if (ans == -1){
    103             printf ("0
    ");
    104             continue;
    105         }
    106         bool ok = 0;
    107         for (int i = 0; i < n; ++ i){
    108             CLR1 (cnt);
    109             dfs (i, 0);
    110 
    111             for (int j = 0; j < n; ++ j) if (i != j && !vis[i][j])
    112                 if (cnt[j] == d[i][j]) ok = 1;
    113         }
    114         if (!ok) printf ("%d
    ", ans);
    115         else printf ("Not Unique!
    ");
    116     }
    117     return 0;
    118 }
    View Code
    ------------------------------------------------------------------
    现在的你,在干什么呢?
    你是不是还记得,你说你想成为岩哥那样的人。
  • 相关阅读:
    GZIP压缩
    对象的constructor属性
    session会话复制
    第一篇博客 iframe自适应高度
    【NOI2012T4】迷失游乐园-环套树+树形DP+期望DP
    【NOI2012T4】迷失游乐园-环套树+树形DP+期望DP
    【HDU5072】Coprime-补集转化+容斥原理+质因数分解
    【HDU5072】Coprime-补集转化+容斥原理+质因数分解
    【NOI2011T1】兔农-矩阵快速幂+乘法逆元
    【NOI2011T1】兔农-矩阵快速幂+乘法逆元
  • 原文地址:https://www.cnblogs.com/plumrain/p/POJ_1679.html
Copyright © 2011-2022 走看看