The Unique MST
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 23180   Accepted: 8235

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!

Source

对于最小生成树(能够用kruskal和prime算法求得,在这里我是用kruskal求得,假设不会请自己百度。),边的权值的和最小称为最小生成树。

而次小生成树就是除了最小生成树外的最小生成树。并且全部的次小生成树都是通过最小生成树的换边得到的。

所以难点就是怎样换边。

对于怎样换边:

1.先求出最小生成树,值为x。

2.一一枚举加入不在生成树上的边(这时候一定形成了一个环)

3.寻找环上的(最小生成树上的边)权值最大值与你所加入不在生成树上的边的权值比較,所得到的差值为min。

因为是一一枚举加入边,min有多个,求出最小的哪一个,所以次小生成树就为x+min。

昨天尽管把这道题A了,但是看到讨论区的測试数据发现自己又一个没有过,然而却AC了。然后今天起床就来研究研究。

发现我的程序是在找最大值。但是假设一个环有分支,它还会去找分支里面的最大值。于是就又优化了一下。

用的优先队列。

先附上第一次做的代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
struct node
{
int a,b,cost;
}c[10005];
int fa[105],tree[105][105],vis[10005],vis_tree[105];//vis数组是对m对数据的标记vis_tree是对最小生成树标记
int n,m,max1;
bool cmp(node x,node y)
{
if(x.cost<y.cost)
return true;
else
return false;
}
int find(int x)//寻找根
{
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
void sec_tree(int a,int b)//查找生成树某条边的最大值(我在这里做的是错误的。假设形成的环有分支,也会查找)
{
vis_tree[a]=1;
if(a==b)
return ;
for(int i=1;i<=n;i++)
if(tree[a][i]&&!vis_tree[i])
{
if(max1<tree[a][i])
max1=tree[a][i];
sec_tree(i,b);
}
}
int main()
{
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
memset(vis,0,sizeof(vis));
memset(tree,0,sizeof(tree));
memset(&c,0,sizeof(&c));
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=0;i<m;i++)
scanf("%d %d %d",&c[i].a,&c[i].b,&c[i].cost);
sort(c,c+m,cmp);
int sum=0;
for(int i=0;i<m;i++)//kruskal算法求最小生成树
{
int x=find(c[i].a);
int y=find(c[i].b);
if(x!=y)
{
fa[x]=y,sum+=c[i].cost;
tree[x][y]=tree[y][x]=c[i].cost;
vis[i]=1;
}
}
int flag=0;
for(int i=0;i<m;i++)
{
if(!vis[i])//不在生成树中的边和形成的环的最大值比較。假设相等,MST不唯一
{
max1=-1;
memset(vis_tree,0,sizeof(vis_tree));
sec_tree(c[i].a,c[i].b);
if(max1==c[i].cost)
{
flag=1;
break;
}
}
}
if(!flag)
printf("%d\n",sum);
else
printf("Not Unique!\n");
}
}

这是优化后的代码。凝视和上面一样。就一个地方不同:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
struct node1
{
int a,b,cost;
friend bool operator<(node1 x,node1 y )
{
return x.cost<y.cost;
}
};
priority_queue<node1>s;
struct node
{
int a,b,cost;
}c[10005];
int fa[105],tree[105][105],vis[10005],vis_tree[105];
int n,m,max1,flag1;
bool cmp1(node x,node y)
{
if(x.cost<y.cost)
return true;
else
return false;
}
int find(int x)
{
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
void sec_tree(int a,int b)
{
node1 temp;
vis_tree[a]=1;
if(a==b)//假设找到a=b,标记一下
{
flag1=1;
}
for(int i=1;i<=n;i++)
if(tree[a][i]&&!vis_tree[i])
{
temp.a=a,temp.b=i,temp.cost=tree[a][i];
s.push(temp);
if(!flag1)//就是在这里和上面不同,假设找不到a=b,那么就把曾经的恢复
s.pop(),vis_tree[i]=0,sec_tree(i,b);
}
}
int main()
{
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
memset(vis,0,sizeof(vis));
memset(tree,0,sizeof(tree));
memset(&c,0,sizeof(&c));
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=0;i<m;i++)
scanf("%d %d %d",&c[i].a,&c[i].b,&c[i].cost);
sort(c,c+m,cmp1);
int sum=0;
for(int i=0;i<m;i++)
{
int x=find(c[i].a);
int y=find(c[i].b);
if(x!=y)
{
fa[x]=y,sum+=c[i].cost;
tree[x][y]=tree[y][x]=c[i].cost;
vis[i]=1;
}
}
int flag=0;
for(int i=0;i<m;i++)
{
if(!vis[i])
{
int flag1=0;
while(!s.empty())
s.pop();
memset(vis_tree,0,sizeof(vis_tree));
sec_tree(c[i].a,c[i].b);
node1 temp;
temp=s.top();
if(temp.cost==c[i].cost)
{
flag=1;
break;
}
}
}
if(!flag)
printf("%d\n",sum);
else
printf("Not Unique!\n");
}
}

poj1679 The Unique MST(判定次小生成树)的更多相关文章

  1. POJ-1679 The Unique MST(次小生成树、判断最小生成树是否唯一)

    http://poj.org/problem?id=1679 Description Given a connected undirected graph, tell if its minimum s ...

  2. POJ1679 The Unique MST 【次小生成树】

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20421   Accepted: 7183 D ...

  3. POJ1679 The Unique MST【次小生成树】

    题意: 判断最小生成树是否唯一. 思路: 首先求出最小生成树,记录现在这个最小生成树上所有的边,然后通过取消其中一条边,找到这两点上其他的边形成一棵新的生成树,求其权值,通过枚举所有可能,通过这些权值 ...

  4. POJ1679 The Unique MST(次小生成树)

    可以依次枚举MST上的各条边并删去再求最小生成树,如果结果和第一次求的一样,那就是最小生成树不唯一. 用prim算法,时间复杂度O(n^3). #include<cstdio> #incl ...

  5. The Unique MST(次小生成树)

    Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 22335   Accepted: 7922 Description Give ...

  6. POJ1679The Unique MST(次小生成树)

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 25203   Accepted: 8995 D ...

  7. poj 1679 The Unique MST【次小生成树】

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24034   Accepted: 8535 D ...

  8. POJ 1679:The Unique MST(次小生成树&amp;&amp;Kruskal)

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19941   Accepted: 6999 D ...

  9. poj 1679 The Unique MST 【次小生成树】【模板】

    题目:poj 1679 The Unique MST 题意:给你一颗树,让你求最小生成树和次小生成树值是否相等. 分析:这个题目关键在于求解次小生成树. 方法是,依次枚举不在最小生成树上的边,然后加入 ...

  10. POJ 1679 The Unique MST (次小生成树)题解

    题意:构成MST是否唯一 思路: 问最小生成树是否唯一.我们可以先用Prim找到一棵最小生成树,然后保存好MST中任意两个点i到j的这条路径中的最大边的权值Max[i][j],如果我们能找到一条边满足 ...

随机推荐

  1. java正則表達式总结

    近期用到的正則表達式 因为近期在做一个android的新闻client.多次用到了正則表達式.因此总结下. 1.使用正則表達式获取Rss资源内的文章内容的图片url 由于在每条新闻浏览的listVie ...

  2. BZOJ 3210 花神的浇花集会 计算几何- -?

    题目大意:给定平面上的n个点,求一个点到这n个点的切比雪夫距离之和最小 与3170不同的是这次选择的点无需是n个点中的一个 首先将每一个点(x,y)变为(x+y,x-y) 这样新点之间的曼哈顿距离的一 ...

  3. Activity 之间 传递 List 封装的对象或者对象

    项目中遇到 从也个页面向还有一个页面跳转传递一个List 封装的对象 .按网上查的资料 须要把 对象 实现 Serializable接口. 写了一下.可是跳转直接崩溃.一直看错误之日找不到原因后来自习 ...

  4. LinkCutTree详解

    LCT详解 没有比这再详细的了, 相信我

  5. javafx ComboBox Event and change cell color

    public class EffectTest extends Application { public static void main(String[] args) { launch(args); ...

  6. c# array arraylist 泛型list

    1 array 数组  是存储相同类型元素的固定大小的数据的顺序集合.在内存中是连续存储的,所以索引速度非常快,而且赋值和修改元素也非常简单. //定义字符串数组 大小为3 string[] str1 ...

  7. ES6--基础语法(一)

    一.支持环境:node.js完全支持,标准浏览器完全支持.二.测试环境: chrome下需要在script标签的最先开始的地方需要添加"use strict". firefox下需 ...

  8. django shell 操作

    插件:django-extensions django-extensions==1.9.8 pip3 install  django-extensions 1.数据库shell 命令(项目目录下) p ...

  9. SpringMVC框架中的异常解析器-ExceptionHandler和HandlerExceptionResolver

    SpringMVC框架中,处理异常还是挺方便的,提供了一个异常解析器. 处理局部异常 @Controller public class AccessController { /** * 处理这个Con ...

  10. [Express] Upload Files with Express

    In this lesson we create a new Express web server app for handling file uploads and persisting them ...