zoukankan      html  css  js  c++  java
  • POJ 1679 The Unique MST (次小生成树kruskal算法)

    The Unique MST

    时间限制: 10 Sec  内存限制: 128 MB
    提交: 25  解决: 10
    [提交][状态][讨论版]

    题目描述

    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'.

    输入

    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 ,1 <= m <= 10000), 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 may be more than one edge to connect 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!



    题意:给一个无向图,判断这个图的最小生成树MST是否是唯一的。如果是唯一的,输出最小生成树的值,如果不是唯一的,输出“Not Unique!”

    思路:kruskal的应用。详细思路与prim版相似,而且时间空间复杂度都得到了一些优化。

    kruskal算法:把所有的边都排个序,从大到小取出,若取出的这条边的两个端点已经连通(用并查集),则换下一条边,n的顶点用n-1条边就可以相连,循环直到n-1条边。

    本题:在找最小生成树(mst)的同时,把选中的边(是第几条)都存下来。再进行多次kruskal算法,每次模拟删除一条边,寻找一条新的边,得到边权和为mst2,判断mst==mst2?即可。

    #include <iostream>
    #include<string>
    #include <cstring>
    #include <queue>
    #include <algorithm>
    using namespace std;
    int n, m;
    int pre[105];
    int Rank[105];
    int mst_e[105];
    struct node
    {
        int u, v, w;
    };
    bool cmp(node x, node y)
    {
        return x.w < y.w;
    }
    void init()//初始化
    {
        int i;
        for (i = 1; i <= n; i++) pre[i] = i;
        memset(Rank, 0, sizeof(Rank));
    }
    int find(int x)//找根
    {
        if (pre[x] == x) return x;
        return pre[x] = find(pre[x]);
    }
    void unite(int x, int y)//压缩合并
    {
        if (Rank[x] < Rank[y]) pre[x] = y;
        else
        {
            pre[y] = x;
            if (Rank[x] == Rank[y]) Rank[x]++;
        }
    }
    int main()
    {
        int t;
        cin >> t;
        while (t--)
        {
            cin >> n >> m;
            init();
            node a[10005];
            int i;
            for (i = 1; i <= m; i++)
            {
                cin >> a[i].u >> a[i].v >> a[i].w;
            }
            sort(a + 1, a + 1 + m, cmp);
            int mst = 0;
            int k = 1;
            for (i = 1; i <= m; i++)//第一次kruskal算法
            {
                int x = find(a[i].u);
                int y = find(a[i].v);
                if (x != y)
                {
                    unite(x, y);
                    mst = mst + a[i].w;
                    mst_e[k++] = i;//  记录下MST的边。
                }
            }
            int edge_num = k-1;
            bool uni = 1;//记录是不是唯一
            int mst2, num;
            for (k =1; k <=edge_num; k++)
            {//遍历每一条MST里的边,一次次模拟删除
                init();//每进行一次kruskal算法,就初始化一次
                mst2 = 0;
                num = 0;
                for (i = 1; i <= m; i++)
                {
                    if (i == mst_e[k]) continue;//模拟删除
                    int x = find(a[i].u);
                    int y = find(a[i].v);
                    if (x != y)
                    {
                        unite(x, y);
                        mst2 = mst2 + a[i].w;
                        num++;
                    }
                    if (num != edge_num) continue;//边数没达到就继续0
                    if (mst2 == mst)
                    {
                        uni = 0;
                        break;
                    }
                }
                if (uni == 0) break;
            }
            if (uni) cout << mst << endl;
            else cout << "Not Unique!" << endl;
        }
        return 0;
    }
  • 相关阅读:
    数据结构-链式结构-队列
    c数据结构-线性结构-队列
    栈的四则运算的运用
    C++/C—函数指针
    向显存写数据x8086
    结构体内存偏移量
    MFC-ComboBox控件的使用
    MFC的Edit text编辑框控件
    C/C++反汇编-各种表达式(加减乘)
    MFC- 学习控件-静态文本
  • 原文地址:https://www.cnblogs.com/caiyishuai/p/8393368.html
Copyright © 2011-2022 走看看