poj 1679 判断MST是不是唯一的 (次小生成树)
判断MST是不是唯一的 如果是唯一的 就输出最小的权值和 如果不是唯一的 就输出Not Unique!
次小生成树就是第二小生成树 如果次小生成树的权值和MST相等 那么MST就不是唯一的
法一:
先求出最小的权值和 然后一条边一条边的删
先标记MST中所使用的边 删边就是屏蔽这条边后 再对剩下的边(不管这些边是否被标记)求MST 如果最后的权值和 与开始算出的最小的那个 相等 就说明不是唯一的
Sample Input
2 //T
3 3 //n m
1 2 1// u v w
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!
Kruskal
# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
# include <cmath>
# define LL long long
using namespace std ; int n ;
const int MAXN=;//最大点数
const int MAXM=;//最大边数
int F[MAXN];//并查集使用
int del[MAXM] ;
struct Edge
{
int u,v,w;
int tag ;
}edge[MAXM];//存储边的信息,包括起点/终点/权值 int tol;//边数,加边前赋值为0
void addedge(int u,int v,int w)
{ edge[tol].u=u;
edge[tol].v=v;
edge[tol].tag = ;
edge[tol++].w=w;
}
bool cmp(Edge a,Edge b)
{//排序函数,讲边按照权值从小到大排序
return a.w<b.w;
}
int find(int x)
{
if(F[x]==-)return x;
else return F[x]=find(F[x]);
}
int Kruskal(int d)//传入点数,返回最小生成树的权值,如果不连通返回-1
{
memset(F,-,sizeof(F)); int cnt=;//计算加入的边数
int ans=;
for(int i=;i<tol;i++)
{
if (i == d) //屏蔽id为d的这一条边
continue ;
int u=edge[i].u;
int v=edge[i].v;
int w=edge[i].w;
int t1=find(u);
int t2=find(v);
if(t1!=t2)
{
ans+=w;
F[t1]=t2;
cnt++;
edge[i].tag = ;
}
if(cnt==n-)break;
}
if(cnt<n-)return -;//不连通
else return ans;
} int main()
{ // freopen("in.txt","r",stdin) ;
int m ;
int T ;
scanf("%d" , &T) ;
while(T--)
{
scanf("%d %d" , &n , &m) ;
int i ;
int u , v , w ;
tol = ;
while(m--)
{
scanf("%d %d %d" , &u , &v , &w) ;
addedge(u , v , w) ;
} sort(edge,edge+tol,cmp);
int ans = Kruskal(-) ; int k = ;
for (i = ; i < tol ; i++)
{
if (edge[i].tag == )
{
del[k] = i ;
k++ ;
}
}
bool flag = ;
int t_ans ;
for (i = ; i < k ; i++)
{
t_ans = Kruskal(del[i]) ;
if (t_ans == ans)
{
flag = ;
break ;
}
}
if (flag)
printf("Not Unique!\n") ;
else
printf("%d\n" , ans) ; }
return ;
}
法二 : Prim
/*
* 次小生成树
* 求最小生成树时,用数组Max[i][j]来表示MST中i到j最大边权
* 求完后,直接枚举所有不在MST中的边,替换掉最大边权的边,更新答案
* 点的编号从0开始
*/
# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
# include <cmath>
# define LL long long
using namespace std ; int n ;
const int MAXN=;
const int INF=0x3f3f3f3f;
bool vis[MAXN];
int lowc[MAXN];
int pre[MAXN];
int Max[MAXN][MAXN];//Max[i][j]表示在最小生成树中从i到j的路径中的最大边权
bool used[MAXN][MAXN];
int cost[MAXN][MAXN];
int Prim()
{
int ans=;
memset(vis,false,sizeof(vis));
memset(Max,,sizeof(Max));
memset(used,false,sizeof(used));
vis[]=true;
pre[]=-;
for(int i=;i<n;i++)
{
lowc[i]=cost[][i];
pre[i]=;
}
lowc[]=;
for(int i=;i<n;i++)
{
int minc=INF;
int p=-;
for(int j=;j<n;j++)
if(!vis[j]&&minc>lowc[j])
{
minc=lowc[j];
p=j;
}
if(minc==INF)return -;
ans+=minc;
vis[p]=true;
used[p][pre[p]]=used[pre[p]][p]=true;
for(int j=;j<n;j++)
{
if(vis[j])Max[j][p]=Max[p][j]=max(Max[j][pre[p]],lowc[p]);
if(!vis[j]&&lowc[j]>cost[p][j])
{
lowc[j]=cost[p][j];
pre[j]=p;
}
}
}
return ans;
} int smst(int ans)
{
int Min=INF;
for(int i=;i<n;i++)
for(int j=i+;j<n;j++)
if(cost[i][j]!=INF && !used[i][j])
{
Min=min(Min,ans+cost[i][j]-Max[i][j]);
}
if(Min==INF)return -;//不存在
return Min;
} int main()
{
// freopen("in.txt","r",stdin) ;
int T;
int m;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
int u,v,w;
for(int i=;i<n;i++)
for(int j=;j<n;j++)
{
if(i==j)cost[i][j]=;
else cost[i][j]=INF;
}
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
u--;v--;
cost[u][v]=cost[v][u]=w;
}
int ans=Prim();
if(ans==-)
{
printf("Not Unique!\n");
continue;
}
if(ans==smst(ans))printf("Not Unique!\n");
else printf("%d\n",ans);
}
return ;
}
poj 1679 判断MST是不是唯一的 (次小生成树)的更多相关文章
- poj 1679 判断最小生成树是否唯一
/* 只需判断等效边和必选边的个数和n-1的关系即可 */ #include<stdio.h> #include<stdlib.h> #define N 110 struct ...
- POJ 1679 判断最小树是否唯一
题意: 给你一个图,问你最小树是否唯一,唯一则输出最小数的权值,不唯一输出Not Unique! 思路: 题目问的是最小树是否唯一,其实也就是在问次小树是否等于最小树,如果等于则 ...
- POJ 1679 The Unique MST (次小生成树)题解
题意:构成MST是否唯一 思路: 问最小生成树是否唯一.我们可以先用Prim找到一棵最小生成树,然后保存好MST中任意两个点i到j的这条路径中的最大边的权值Max[i][j],如果我们能找到一条边满足 ...
- POJ 1679 The Unique MST(判断最小生成树是否唯一)
题目链接: http://poj.org/problem?id=1679 Description Given a connected undirected graph, tell if its min ...
- POJ-1679 The Unique MST(次小生成树、判断最小生成树是否唯一)
http://poj.org/problem?id=1679 Description Given a connected undirected graph, tell if its minimum s ...
- poj 1679 The Unique MST 【次小生成树+100的小数据量】
题目地址:http://poj.org/problem?id=1679 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 Outpu ...
- poj 1679 The Unique MST (次小生成树模板题)
Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spann ...
- POJ1679 The Unique MST —— 次小生成树
题目链接:http://poj.org/problem?id=1679 The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total S ...
- POJ1679The Unique MST(次小生成树)
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 25203 Accepted: 8995 D ...
随机推荐
- Hive记录-Hive调优
1.Join优化 a.map join b.reduce join 小表为驱动表,或直接将小表加载到内存,做map端join,它的关键字为/*+MAP JOIN(t1)*/ 如果想自动开启map端Jo ...
- Study 5 —— 流程控制
if 条件: 满足条件后要执行的代码else: if条件不满足就执行这里 #_*_coding:utf-8_*_ ------------------------------------------- ...
- Mac改键软件Karabiner使用教程
Mac改键软件Karabiner使用教程 目前Mac上比较好用的改键软件是Karabiner,不过对于最新的Sierra系统,Karabiner失效了.这里介绍的实际上是Karabiner-Eleme ...
- 关于windows下的虚拟机Homestead在推送代码上github 步骤
1.ssh 秘钥登录配置 使用以下命令检查主机是否生成SSH Key: > ls -al ~/.ssh 2.如果有秘钥,那就跳过这个步骤,如果没有秘钥,则运行以下命令来生成秘钥: ssh-key ...
- python - class类 (四) 三大特性之一 :继承
继承: #继承 #什么时候用继承? # 1.当类之间有显著的不同,并且较小的类是较大的类的所需的组建时,用组合比较好. # 2.当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好 # ...
- Android判断当前是否在主线程
Android开发中, 有时需要判断当前线程到底是主线程, 还是子线程, 例如: 我们在自定义View时, 想要让View重绘, 需要先判断当前线程到底是不是主线程, 然后根据判断结果来决定到底是调用 ...
- libSVM在matlab下的使用安装
1) 从LIBSVM的官网http://www.csie.ntu.edu.tw/~cjlin/libsvm/上下载最新版本的LIBSVM,当前版本为libsvm-3.18.zip 2) 解压压缩包到电 ...
- C++学习5-面向对象编程基础(构造函数、转换构造、静态数据成员、静态成员函数、友元)
知识点学习 类 const作用 C语言的const限定符的含义为"一个不能改变值的变量",C++的const限定符的含义为"一个有类型描述的常量": const ...
- Zookeeper简介与集群搭建【转】
Zookeeper简介 Zookeeper是一个高效的分布式协调服务,可以提供配置信息管理.命名.分布式同步.集群管理.数据库切换等服务.它不适合用来存储大量信息,可以用来存储一些配置.发布与订阅等少 ...
- 最大流算法-最高标号预流推进(HLPP)
昨天我们学习了ISAP算法,它属于增广路算法的大类.今天学习的算法是预流推进算法中很高效的一类--最高标号预流推进(HLPP). 预流推进 预流推进是一种很直观的网络流算法.如果给到一个网络流让你手算 ...