POJ 1679 The Unique MST (the second smallest spanning tree O(mlogm))

Description

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:

  1. V '= V.
  2. 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’.

Input
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 (xi, yi, wi), 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.
Output
For each input, if the MST is unique, print the total cost of it, or otherwise print the string ‘Not Unique!’.

Consider the uniqueness of the minimum spanning tree. If an edge is not in the edge set of the minimum spanning tree, and can replace the other edge with the same weight and in the edge set of the minimum spanning tree. Then, this minimum spanning tree is not unique.
For the Kruskal algorithm, as long as the edges calculated as the current weight value can be placed several, if the two values ​​are not the same, then it means that these edges and the previous edge produce a ring (in this ring There must be at least two edges with the current weight, otherwise this edge cannot be placed according to the union search), that is, the minimum spanning tree is not unique.
To find the edge with the same weight as the current edge, we only need to record the head and tail pointers, and the monotonic queue can be used in O (α (m)) O(α(m))O ( α ( m ) ) (m is the number of edges) is an excellent solution to this problem in the time complexity (basically the same time as the original algorithm).

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>

using namespace std;
const int N = 500007;

int n, m;
int fa[N];
struct node{
    
    
    int x, y, z;
    bool operator<(const node &t)const {
    
    
        return z < t.z;
    }
}e[N];

int find(int x){
    
    
    if(fa[x] == x)return x;
    return fa[x] = find(fa[x]);
}

int main(){
    
    
    int t;
    scanf("%d", &t);
    while(t -- ){
    
    
        int cnt = 0;
        scanf("%d%d", &n, &m);
        for(int i = 0; i <= n; ++ i)
            fa[i] = i;

        for(int i = 1; i <= m; ++ i){
    
    
            int x, y, z;
            scanf("%d%d%d", &x, &y, &z);
            e[++ cnt] = (node){
    
    x, y, z};
        }
        sort(e + 1, e + 1 + cnt);
        //sum1为相同权值大小 可以 添加到最小生成树中的边数(当前还没放呢)
        //sum2为相同权值大小 实际 添加到最小生成树中的边数
        //如果最小生成树唯一,则sum1 == sum2
        int tail = 0, ans = 0, sum1 = 0, sum2 = 0, num = 0;
        bool flag = 1;
        for(int i = 1; i <= m + 1; ++ i){
    
    
            if(i > tail){
    
    //开始新的一个权值的边以后
                if(sum1 != sum2){
    
    
                    flag = 0;
                    break;
                }
                sum1 = 0;
                //要到 m+1 才能把 m 条边都扫一遍
                for(int j = i; j <= m + 1; ++ j){
    
    
                    if(e[i].z != e[j].z){
    
    
                        tail = j - 1;
                        break;
                    }
                    if(find(e[j].x) != find(e[j].y))
                        sum1 ++ ;
                }
                sum2 = 0;
            }

            if(i > m)break;

            int x = find(e[i].x);
            int y = find(e[i].y);
            if(x != y && num != n - 1){
    
    
                fa[x] = y;
                sum2 ++ ;
                num ++ ;
                ans += e[i].z;
            }
        }
        if(flag)
            printf("%d\n", ans);
        else printf("Not Unique!\n");
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_45697774/article/details/108552652