poj1679 The Unique MST

  题目大意:给定一个联无向网,判断它的最小生成树是否唯一。

The Unique MST

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 20421 Accepted: 7183

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!

1:在prim()中记录每个入树点的前缀点,在一次prim()之后对每个入树点a  遍历其它所有的入树点,
   看该入树点a的入树方式是否唯一,若不唯一,则存在多个最小生成树!.
<span style="font-size:18px;">#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<queue>
#include<math.h>
#include<set>
#include<vector>
using namespace std;
#define maxn 150
#define MM 100000000
int n,m,sum;
int v[maxn];
int d[maxn];
int W[maxn][maxn];
int w[maxn][maxn];
int vis[maxn];
int Vis[maxn][maxn];
int conut;
void prim()
{
     sum=0;
     memset(v,0,sizeof(v));
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)
        d[i]=(i==1?0:MM);
    for(int j=1;j<=n;j++)
    {
        int x,mm=MM;
        for(int i=1;i<=n;i++)
        if(d[i]<mm && !v[i])
        mm=d[x=i];
        sum+=mm;
        v[x]=1;
        for(int i=1;i<=n;i++)
            if(d[i]>w[x][i])
            {

               d[i]=w[x][i];
               vis[i]=x;
            }
    }
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        conut=0;
        int a,b,c;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
             w[i][j]=MM;
        for(int i=1;i<=m;i++)
        {
             scanf("%d%d%d",&a,&b,&c);
             if(w[a][b]>c)
                w[a][b]=w[b][a]=c;
        }
        prim();
        for(int i=1;i<=n;i++)
        {
            if(vis[i])
            for(int j=1;j<=n;j++)
            if(j!=vis[i] && v[j] && w[j][i]==w[i][vis[i]])
            conut=1;
        }

        if(conut)
         printf("Not Unique!\n");
         else
            printf("%d\n",sum);
    }
    return 0;
}
</span>

******************####################################################**********************
 
2:逐个删边再次prim();容易想到,复杂度高O(n^4) 在每个点入树的时候用数组vis标记改点的入树“支点”。----这是 我做这题时不知道怎么处理的地方。

<span style="font-size:18px;">  #include<iostream>
    #include<algorithm>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<queue>
    #include<math.h>
    #include<set>
    #include<vector>
    using namespace std;
    #define maxn 150
    #define MM 100000000
    int n,m,sum;
    int v[maxn];
    int d[maxn];
    int W[maxn][maxn];
    int w[maxn][maxn];
    int vis[maxn];
    int Vis[maxn][maxn];
    void prim()
    {
         sum=0;
         memset(v,0,sizeof(v));
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
            d[i]=(i==1?0:MM);
        for(int j=1;j<=n;j++)
        {
            int x,mm=MM;
            for(int i=1;i<=n;i++)
                if(d[i]<mm && !v[i])
                mm=d[x=i];
                sum+=mm;
            v[x]=1;
            for(int i=1;i<=n;i++)
                if(d[i]>w[x][i])
                {
                     d[i]=w[x][i];
                    vis[i]=x;        //  保存入树点的入树“支点”
                }
        }
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int a,b,c;
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                 w[i][j]=MM;
            for(int i=1;i<=m;i++)
            {
                 scanf("%d%d%d",&a,&b,&c);
                 if(w[a][b]>c)
                    w[a][b]=w[b][a]=c;
            }
            prim();
            memset(Vis,0,sizeof(Vis));
           for(int i=n;i>1;i--)
           {
               if(vis[i])
                Vis[vis[i]][i]=Vis[i][vis[i]]=1;   // 标记入树的边
           }
           for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            W[i][j]=w[i][j];                     //用W数组保存各边的原始数据,Sum保存最小的距离,conut标记是否有不止一个最小生成树。
            int SUM=sum,conut=0,cc=0;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                if(Vis[i][j]==1)            //如果该边在第一次prim中已入树,删除该边,再次prim();
             {
                if(conut)
                    break;
                 for(int ii=1;ii<=n;ii++)
                for(int jj=1;jj<=n;jj++)
                w[ii][jj]=W[ii][jj];
                w[i][j]=w[j][i]=MM;
                prim();
                if(SUM==sum)             // 一旦删除边后所求最小生成树与删除边前所求相等 ----最小生成树不唯一。conut=1;
                {
                    conut=1;            //还可以 用conut++ 来求最小生成树的个数。
                }
            }
                if(!conut)
                printf("%d\n",SUM);
                else
                printf("Not Unique!\n");

        }
        return 0;
}</span>

poj1679 The Unique MST

时间: 2024-10-05 05:04:41

poj1679 The Unique MST的相关文章

POJ1679 The Unique MST 【次小生成树】

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20421   Accepted: 7183 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire

POJ1679 The Unique MST【Kruskal】【次小生成树】

The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 21304 Accepted: 7537 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undirected

POJ1679 The Unique MST(Kruskal)(最小生成树的唯一性)

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 27141   Accepted: 9712 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire

POJ1679 The Unique MST(次小生成树)

可以依次枚举MST上的各条边并删去再求最小生成树,如果结果和第一次求的一样,那就是最小生成树不唯一. 用prim算法,时间复杂度O(n^3). 1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 #define MAXN 111 5 #define INF (1<<30) 6 struct Edge{ 7 int u,v; 8 }edge[MAXN]; 9 int NE; 10 11 int n

POJ1679 The Unique MST 生成树+DFS

题意:求一个无向图的最小生成树与次小生成树的边权和是否相等 题解: 首先有一个性质,就是最小生成树上的任意两点的距离就是其在原图中的最短路,严格的证明我不会- -,但是由于Prim Dijkstra算法的过程完全相同,所以这个性质比较显然(不会证就不会证呗为何还要找理由QAQ) 还要一条性质就是无向MST上加入一条边一定会形成一个环,因此我们可以枚举加入一条不在MST上的边e,然后删除MST上形成的环中除e之外的最长的一条边,得到了一个新的最小生成树,由于e一定大于等于删除的那条边,因此得到的新

poj1679——The Unique MST(次小生成树,Kruskal)

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 followin

POJ-1679 The Unique MST (判断最小生成树的唯一性)

<题目链接> 题目大意: 给定一张无向图,判断其最小生成树是否唯一. 解题分析: 对图中每条边,扫描其它边,如果存在相同权值的边,则标记该边:用kruskal求出MST. 如果MST中无标记的边,则该MST唯一:否则,在MST中依次去掉标记的边,再求MST,若求得MST权值和原来的MST 权值相同,则MST不唯一. #include <cstdio> #include <iostream> #include <cstring> #include <al

POJ1679 The Unique MST 题解 次小生成树 题解 Kruskal+暴力LCA解法(因为倍增不会写)

题目链接:http://poj.org/problem?id=1679 题目大意: 给你一个简单连通图,判断他的最小生成树是否唯一. 解题思路: 首先(我这里用Kruskal算法)求出它的最小生成树(以下简称MST)以及对应的边,然后构造出这棵MST. 然后我们枚举图上每一条不在此MST上的边,假设这条边的两个端点是 \(u\) 和 \(v\),边权为 \(w\) ,求MST上 \(u\) 到 \(v\) 的树链上的最大边的值是否等于 \(w\),如果等于 \(w\) 就说明 MST 不唯一.

[POJ1679]The Unique MST 次小生成树

题目链接:http://poj.org/problem?id=1679 给你一个图的连通情况,询问你此图的最小生成树是否唯一. 假如最小生成树唯一,即生成树连通所有节点的权值和唯一.假如不唯一,那么存在另一条最小生成树使得权值等于之前最小生成树的权值. 换个思路考虑,也就是次小生成树的权值与最小生成树的权值相同,那么问题就变成了求次小生成树的权值. 我选择的是先求出最小生成树,将树上用到的边都保存下来.接着分别将每一条用到的边摘下来,再求一次最小生成树.假如不包含当前删掉的边生成的生成树的所选边