POJ1679判断最小生成树的唯一性
题意:
判断最小树是否唯一。
思路:
我用了两种方法,主要就是好久没敲了,找个水题练练手,第一种就是先一遍最小生成树,然后枚举最小生成树上的每一条边,然后取消这条边,在跑一遍最小生成树,就这样一直跑最小生成树,如果找到了一颗和之前的那个一样的,那么就是不唯一,第二种方法也是先最小树,然后枚举,在枚举的时候不是继续重新跑,而是断开当前边,把树分成两个集合<两次深搜实现>,然后在枚举这连个集合之间是否可以找到一个可以代替当前枚举的最小树的边,实现复杂度的话应该是第二种快点,但理论上也快不多少,只是为了练练手,在多说一句,第二种方法和求次小树的思路有点像,但是次小树可以再这个上面进行dp优化,其实这个题目也可以直接判断次小树是否等于最小树。好像有点说多了。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 110
using namespace std;
typedef struct
{
int x ,y ,c;
}EDGE;
EDGE edge[N*N];
int mer[N] ,mst[N];
int finds(int x)
{
return x == mer[x] ? x : mer[x] = finds(mer[x]);
}
bool camp(EDGE a ,EDGE b)
{
return a.c < b.c;
}
int MST(int n ,int m ,int co)
{
for(int i = 1 ;i <= n ;i ++)mer[i] = i;
int Ans = 0 ,sum = 0;
for(int i = 1 ;i <= m ;i ++)
{
if(i == co) continue;
int xx = finds(edge[i].x);
int yy = finds(edge[i].y);
if(xx != yy)
{
Ans += edge[i].c ,sum ++ ;
mer[xx] = yy;
if(co == -1) mst[sum] = i;
}
if(sum == n - 1) break;
}
return Ans;
}
int main ()
{
int t ,i ,n ,m;
scanf("%d" ,&t);
while(t--)
{
scanf("%d %d" ,&n ,&m);
for(i = 1 ;i <= m ;i ++)
scanf("%d %d %d" ,&edge[i].x ,&edge[i].y ,&edge[i].c);
sort(edge + 1 ,edge + m + 1 ,camp);
int Ans = MST(n ,m ,-1);
for(i = 1 ;i < n ;i ++)
{
int tmp = MST(n ,m ,mst[i]);
if(Ans == tmp) break;
}
i == n || m == n - 1? printf("%d\n" ,Ans) : puts("Not Unique!");
}
return 0;
}
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 110
using namespace std;
typedef struct
{
int x ,y ,c;
}EDGE;
typedef struct
{
int to ,next;
}STAR;
EDGE edge[N*N];
STAR E[N*N];
int map[N][N] ,mer[N] ,mark[N];
int list[N] ,tot ,mst[N];
int L[N] ,R[N] ,ll ,rr;
void add(int a, int b)
{
E[++tot].to = b;
E[tot].next = list[a];
list[a] = tot;
}
int finds(int x)
{
return x == mer[x] ? x : mer[x] = finds(mer[x]);
}
int minn(int x ,int y)
{
return x < y ? x : y;
}
bool camp(EDGE a ,EDGE b)
{
return a.c < b.c;
}
int MST(int n ,int m)
{
for(int i = 1 ;i <= n ;i ++) mer[i] = i;
int Ans = 0 ,sum = 0;
memset(list ,0 ,sizeof(list)) ,tot = 1;
for(int i = 1 ;i <= m ;i ++)
{
int xx = finds(edge[i].x);
int yy = finds(edge[i].y);
if(xx != yy)
{
Ans += edge[i].c ,sum ++;
mer[xx] = yy;
mst[sum] = i;
add(edge[i].x ,edge[i].y);
add(edge[i].y ,edge[i].x);
}
if(sum == n - 1) break;
}
return Ans;
}
void DFS1(int x)
{
for(int k = list[x] ;k ;k = E[k].next)
{
int to = E[k].to;
if(mark[to]) continue;
mark[to] = 1;
L[++ll] = to;
DFS1(to);
}
}
void DFS2(int x)
{
for(int k = list[x] ;k ;k = E[k].next)
{
int to = E[k].to;
if(mark[to]) continue;
mark[to] = 1;
R[++rr] = to;
DFS2(to);
}
}
int main ()
{
int t ,n ,m ,i ,j ,mk;
scanf("%d" ,&t);
while(t--)
{
scanf("%d %d" ,&n ,&m);
for(i = 1 ;i <= n ;i ++)
for(j = 1 ;j <= n ;j ++)
map[i][j] = 100000000;
for(i = 1 ;i <= m ;i ++)
{
scanf("%d %d %d" ,&edge[i].x ,&edge[i].y ,&edge[i].c);
int x = edge[i].x ,y = edge[i].y;
map[x][y] = map[y][x] = minn(map[x][y] ,edge[i].c);
}
sort(edge + 1 ,edge + m + 1 ,camp);
int Ans = MST(n ,m);
if(m == n - 1)
{
printf("%d\n" ,Ans);
continue;
}
mk = 0;
for(i = 1 ;i < n && !mk;i ++)
{
memset(mark ,0 ,sizeof(mark));
int l = edge[mst[i]].x ,r = edge[mst[i]].y;
mark[l] = mark[r] = 1;
ll = rr = 0;
L[++ll] = l ,R[++rr] = r;
DFS1(l) ,DFS2(r);
for(int j = 1 ;j <= ll && !mk;j ++)
{
for(int k = 1 ;k <= rr && !mk ;k ++)
{
if(L[j] == edge[mst[i]].x && R[k] == edge[mst[i]].y || L[j] == edge[mst[i]].y && R[k] == edge[mst[i]].x)
continue;
if(map[L[j]][R[k]] == edge[mst[i]].c) mk = 1;
}
}
}
mk ? printf("Not Unique!\n"): printf("%d\n" ,Ans);
}
return 0;
}
POJ1679判断最小生成树的唯一性的更多相关文章
- poj1679(判断最小生成树是否唯一)
题意:给出n个点,m条边,要你判断最小生成树是否唯一. 思路:先做一次最小生成树操作,标记选择了的边,然后枚举已经被标记了的边,判断剩下的边组成的最小生成树是否与前面的相等,相等,则不唯一,否则唯一. ...
- POJ-1679 The Unique MST (判断最小生成树的唯一性)
<题目链接> 题目大意: 给定一张无向图,判断其最小生成树是否唯一. 解题分析: 对图中每条边,扫描其它边,如果存在相同权值的边,则标记该边:用kruskal求出MST. 如果MST中无标 ...
- POJ1679 The Unique MST(Kruskal)(最小生成树的唯一性)
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 27141 Accepted: 9712 D ...
- POJ-1679 The Unique MST(次小生成树、判断最小生成树是否唯一)
http://poj.org/problem?id=1679 Description Given a connected undirected graph, tell if its minimum s ...
- PTA 7-4 最小生成树的唯一性 (35分)
PTA 7-4 最小生成树的唯一性 (35分) 给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一.本题就要求你计算最小生成树的总权重,并且判断其是否唯一. 输入格式: ...
- poj1679(最小生成树)
传送门:The Unique MST 题意:判断最小生成树是否唯一. 分析:先求出原图的最小生成树,然后枚举删掉最小生成树的边,重做kruskal,看新的值和原值是否一样,一样的话最小生成树不唯一. ...
- 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 (次小生成树 判断最小生成树是否唯一)
题目链接 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. De ...
- K - The Unique MST (最小生成树的唯一性)
Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spann ...
随机推荐
- WebRTC 音视频同步原理与实现
所有的基于网络传输的音视频采集播放系统都会存在音视频同步的问题,作为现代互联网实时音视频通信系统的代表,WebRTC 也不例外.本文将对音视频同步的原理以及 WebRTC 的实现做深入分析. 时间戳 ...
- P2516 [HAOI2010]最长公共子序列 题解(LCS)
题目链接 最长公共子序列 解题思路 第一思路: 1.用\(length[i][j]\)表示\(a\)串的前\(i\)个字符与\(b\)串的前\(j\)个字符重叠的最长子串长度 2.用\(num[i][ ...
- SPOJ QTree【树链剖分】
一 题目 QTREE 二 分析 第一道树链剖分的题,写的好艰难啊. 题意还是比较好理解的,就是在树上操作. 对于修改,题中要求的是单点修改,就算是直接树上操作也是非常简单的. 对于查询,查询的时候,是 ...
- 使用dcmtk库读取.dcm文件并获取信息+使用OpenCV显示图像
借助VS2013和OpenCV的绘图功能,在工程DICOMReader.sln中实现了对单张.dcm图像的读取与显示,以下是详细步骤. 前期准备工作 编译器:VS2013 库:dcmtk-3.6.0( ...
- Centos7下安装JDK详细过程记录
1.查询系统是否安装了java: [root@bogon ~]# java -version 根据上图显示,系统默认安装了Openjdk,它和我们使用的java jdk有些区别(具体的可度娘),所以需 ...
- python中zip函数的使用
zip(*iterables) zip可以将多个可迭代对象组合成一个迭代器对象,通过迭代取值,可以得到n个长度为m的元组.其中n为长度最短可迭代对象的元素个数,m为可迭代对象的个数.并且每个元组的第i ...
- java 基础知识储备
初始JAVA JAVA 帝国的诞生 1972年C诞生 贴近硬件,运行极快,效率极高. 操作系统,编译器,数据库,网络系统等 指针和内存管理 1982年C++诞生 面向对象 兼容C 图形领域.游戏等 纵 ...
- Shell prompt(PS1) 与 Carriage Return(CR) 的关系?-- Shell十三问<第二问>
Shell prompt(PS1) 与 Carriage Return(CR) 的关系?-- Shell十三问<第二问> 当你成功登录进一个文字界面之后,大部份情形下,你会在荧幕上看到一个 ...
- Ansible 教程
[注]本文译自:https://www.edureka.co/blog/ansible-tutorial/ 在阅读本文之前,你应该已经知道,Ansible 构成了 DevOps 认证的关键部分,它 ...
- 【洛谷】P1294 高手去散步
题目背景 高手最近谈恋爱了.不过是单相思."即使是单相思,也是完整的爱情",高手从未放弃对它的追求.今天,这个阳光明媚的早晨,太阳从西边缓缓升起.于是它找到高手,希望在晨读开始之前 ...