判断最小生成树是否唯一

http://poj.org/problem?id=1679

The Unique MST
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 20487 Accepted: 7207

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

Sample Input

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

Sample Output

3
Not Unique!
程序:

#include"stdio.h"
#include"string.h"
#include"stack"
#include"math.h"
#include"algorithm"
#include"stdlib.h"
#define M 222
#define inf 100000000
#define eps 1e-12
using namespace std;
struct node
{
    int u,v,w;
}e[M*M];
int cmp(node a,node b)
{
    return a.w<b.w;
}
int f[M];
int finde(int x)
{
    if(x!=f[x])
        f[x]=finde(f[x]);
    return f[x];
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m,i,j;
        scanf("%d%d",&n,&m);
        for(i=0;i<m;i++)
            scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        sort(e,e+m,cmp);
        int num=0;
        int fuck=0;
        int sum=0;
        for(i=1;i<=n;i++)
            f[i]=i;
        for(i=0;i<m;)
        {
            j=i;
            while(e[i].w==e[j].w&&j<m)
            {
                int x=finde(e[j].u);
                int y=finde(e[j].v);
                if(x!=y)
                    fuck++;
                j++;
            }
            j=i;
            while(e[i].w==e[j].w&&j<m)
            {
                int x=finde(e[j].u);
                int y=finde(e[j].v);
                if(x!=y)
                {
                    f[x]=y;
                    sum+=e[i].w;
                    num++;
                }
                j++;
            }
            i=j;
            if(num==n-1)
                break;
        }
        if(fuck>num)
            printf("Not Unique!\n");
        else
            printf("%d\n",sum);
        //printf("%d %d\n",fuck,num);
    }
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 题目要求计算带权无向最小生成树的总权重,并判断最小生成树是否唯一。如果是连通的,则至少存在一棵最小生成树最小生成树是指在一个连通的无向中,选取一些边,使得这些边构成一棵生成树,并且这棵生成树的边权之和最小。 如果最小生成树唯一,则说明在这个中,选取的边的集合是唯一的,而且这个集合的边权之和最小。如果最小生成树唯一,则说明在这个中,存在多个选取的边的集合,使得这些集合的边权之和都是最小的。 因此,我们需要先求出这个最小生成树,并计算其边权之和。然后,我们再判断是否存在其他的最小生成树。 求解最小生成树的算法有很多种,比如Kruskal算法和Prim算法等。这里不再赘述。判断最小生成树是否唯一的方法也有很多种,比如比较两个最小生成树的边集是否相同等。 ### 回答2: 对于任意一张带权无向,如果它是连通,那么最小生成树一定存在。最小生成树是一颗只包含原所有节点的树,并且这颗树所有边的权值之和最小。 最小生成树并不唯一,即可能存在多颗树,权值和相同,都是最小生成树。如何判断最小生成树是否唯一呢?一个简单的方法是尝试构造两颗不同的最小生成树。如果两颗树边的数目相同且每条边的权值都相同,则说明最小生成树唯一。 计算最小生成树的总权重可使用经典的Prim算法和Kruskal算法。Prim算法从一个点开始,按照某种规则不断加入点和边,最后形成最小生成树。Kruskal算法则通过不断选取当前未被选中的最小边,最终也可以得到最小生成树。两种算法的时间复杂度均为O(ElogE),其中E为边的数目。 对于稠密,Prim算法更加高效,因为它只需考虑点周围的边。而对于稀疏,Kruskal算法则更加高效,因为它只需对边进行排序。 综上所述,对于一张连通的带权无向,无论采用Prim算法还是Kruskal算法,都可以找到最小生成树并计算出其权值和。并且可以通过构造两颗不同的最小生成树判断是否唯一。 ### 回答3: 最小生成树是指在一个无向连通带权中,选取一些边连接所有节点,并且花费较小的一种方案,使得中不形成回路,从而令变成一棵生成树。在带权无向连通中,最小生成树唯一的当且仅当中每一条边的权值都是唯一的。 在求解最小生成树的过程中,Kruskal算法和Prim算法是最常用且合适的两个算法,它们的时间复杂度均为O(ElogE)。 如果一个带权无向连通,那么就至少存在一棵最小生成树。此时,我们可以依据Kruskal算法或Prim算法,在中选择边以建立最小生成树,同时记下每一条被选中的边的权值,最后将它们相加即为最小生成树的权重。而最小生成树并不唯一,因为有可能存在两条或多条边的权值相等,且它们在最小生成树中都可以被选择。此时我们可以依据算法的贪心选择特性,在构建最小生成树的过程中,选择哪一条具有相同权值的边的顺序是会影响到最终的生成树。 因此,我们可以用Kruskal或Prim算法计算最小生成树的总权重,同时在构建最小生成树的过程中,记录下同权边的情况,如果同权边都被选中了,说明最小生成树唯一。否则最小生成树唯一的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值