ACM/ICPC 之 判别MST唯一性-Kruskal解法(POJ1679)

判别MST是否唯一的例题。



POJ1679-The Unique MST

 

  题意:给定图,求MST(最小生成树)是否唯一,唯一输出路径长,否则输出Not Unique!

  题解:MST是否唯一取决于是否有两边权值相同(其中一条边在第一次求得的MST内,另一条在MST外)的情况。

     如果存在这样的边,则需要逐次删除MST内的该边,再次求MST,如果此次求得的MST路长与第一次MST相同,则确实存在不唯一的MST

     否则,一定不存在多条MST。

  1 //Kruskal-判断MST是否唯一
  2 //Time:0MS    Memory:868K
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<algorithm>
  7 using namespace std;
  8
  9 #define MAX 101
 10
 11 struct Edge {
 12     int u, v;
 13     int w;
 14     bool used;    //First Used
 15     bool del;    //Kruskal是否不考虑此边
 16     friend bool operator < (Edge e1, Edge e2) { return e1.w < e2.w; }
 17 }e[MAX*MAX];
 18
 19 int n, m;
 20 bool first;    //是否第一次求MST
 21 int fa[MAX];
 22 int del[MAX*MAX], len;    //须逐次删除的边
 23 int minroad;    //第一次MST结果
 24
 25 int Find(int x)
 26 {
 27     return fa[x] < 0 ? x : fa[x] = Find(fa[x]);
 28 }
 29
 30 void Union(int r1, int r2)
 31 {
 32     r1 = Find(r1);
 33     r2 = Find(r2);
 34     int num = fa[r1] + fa[r2];
 35     if (fa[r1] < fa[r2])
 36     {
 37         fa[r2] = r1;
 38         fa[r1] = num;
 39     }
 40     else {
 41         fa[r1] = r2;
 42         fa[r2] = num;
 43     }
 44 }
 45
 46 bool kruskal()
 47 {
 48     memset(fa, -1, sizeof(fa));
 49     int num = 0;
 50     int mind = 0;
 51     for (int i = 0; i < m; i++)
 52     {
 53         if (e[i].del)    continue;
 54         if (Find(e[i].u) == Find(e[i].v))    continue;
 55         Union(e[i].u, e[i].v);
 56         if (first) {
 57             minroad += e[i].w;
 58             e[i].used = true;
 59         }
 60         mind += e[i].w;
 61         if (mind > minroad) return true;
 62         if (++num == n - 1) break;
 63     }
 64
 65     return false;
 66 }
 67
 68 int main()
 69 {
 70     int T;
 71     scanf("%d", &T);
 72     while (T--)
 73     {
 74         scanf("%d%d", &n, &m);
 75         memset(e, 0, sizeof(e));
 76         for (int i = 0; i < m; i++)
 77             scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
 78
 79         len = 0;
 80         sort(e, e + m);
 81         for (int i = 0; i < m; i++)
 82             if (e[i].w == e[i + 1].w)
 83             {
 84                 if(del[len-1] != i) del[len++] = i;
 85                 del[len++] = i + 1;
 86             }
 87
 88         minroad = 0;
 89         first = true;
 90         kruskal();
 91         first = false;
 92
 93         bool unique = true;
 94         for (int i = 0; i < len; i++)
 95         {
 96             if (!e[del[i]].used) continue;    //使用过的才删除
 97             e[del[i]].del = true;    //删除
 98             if (!kruskal())
 99             {
100                 printf("Not Unique!\n");
101                 unique = false; break;
102             }
103             e[del[i]].del = false;    //恢复
104         }
105
106         if (unique)
107             printf("%d\n", minroad);
108     }
109
110
111
112     return 0;
113 }
时间: 2024-10-08 23:47:39

ACM/ICPC 之 判别MST唯一性-Kruskal解法(POJ1679)的相关文章

ACM/ICPC 之 Kruskal范例(POJ1128(ZOJ1083))

最小生成树范例,Kruskal解法-以边为主体扩展最小生成树,需要利用并查集. ZOJ1203-Swordfish 题意:求n个给定平面坐标的城市中的一条平面距离上的最短路长(保留两位小数) 题解:这道题数据不是很大,用Kruskal和Prim等算法都能够做. Kruskal的算法思路是以边为主体扩展结点,即先选取权值最少的边,将两个不连通的端点加入到同一集合中(使其连通),舍去该边,接着找权值次小的,以此类推... 如果两个端点连通,则直接舍去该边. 因此可以先将所有边依据权值大小排序后,然后

ACM/ICPC 之 Prim范例(ZOJ1586-POJ1789(ZOJ2158))

两道Prim解法范例题型,简单的裸Prim,且两题相较以边为重心的Kruskal解法而言更适合以点为重心扩展的Prim解法. ZOJ1586-QS Network 题意:见Code 题解:直接的MST题型,本题的图为稠密图,因此适合以点为扩展导向的Prim算法(代码量也较少). 大抵是先以某点A为中心,标记点A,访问其邻接点,更新全图到该点的距离(不通路以INF表示),找出最短距离的点B 标记最短距离的B点,然后访问其邻接点,更新邻接点到B点的最短距离,找出最短距离的点C...以此类推... 将

2016 ACM/ICPC Asia Regional Dalian Online 1006 /HDU 5873

Football Games Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 439    Accepted Submission(s): 157 Problem Description A mysterious country will hold a football world championships---Abnormal Cup

【转】[email&#160;protected]&#183;ACM/ICPC 回忆录

转自:http://hi.baidu.com/ordeder/item/2a342a7fe7cb9e336dc37c89 2009年09月06日 星期日 21:55 初识ACM最早听说ACM/ICPC这项赛事是在大三上的算法课上张老师提到的,当时我们学校的组织参加这项活动才刚刚起步,我也没太在意,总觉得那是非常遥远的事,事实上当时我也从未相当如今我们能获得现在的成绩.真正踏入ACM/ICPC这个神奇的世界,不得不提到2004那一年我们学校的参赛队伍xmutank,正是听了pipo师兄的精彩演讲以

[转]浅谈ACM ICPC的题目风格和近几年题目的发展

斯坦福大学 王颖 ACM ICPC的比赛形式一般是五个小时八个题目,综合考察选手的数学能力.算法能力.coding能力和debug能力,还有团队配合能力.数学方面主要强调组合数学.图论和数论这三个方面的能力:而算法的覆盖范围很广,涉及了大部分经典的算法,和少量较前沿的算法.由于每道题目都需要通过所有的测试数据才能得分,并且需要精确解,这限制了Approximation algorithm在一些NP-hard的题目中的运用,从而使得搜索和剪枝策略对于NP-hard的题目非常重要. Final的题目

2016 ACM/ICPC亚洲区青岛站现场赛(部分题解)

摘要 本文主要列举并求解了2016 ACM/ICPC亚洲区青岛站现场赛的部分真题,着重介绍了各个题目的解题思路,结合详细的AC代码,意在熟悉青岛赛区的出题策略,以备战2018青岛站现场赛. HDU 5984 Pocky 题意 给出一根棒子(可以吃的)的长度x和切割过程中不能小于的长度d,每次随机的选取一个位置切开,吃掉左边的一半,对右边的棒子同样操作,直至剩余的长度不大于d时停止.现在给出x和d,问切割次数的数学期望是多少. 解题思路 当看到第二个样例2 1时,结果是1.693147,联想到ln

《ACM/ICPC 算法训练教程》读书笔记一之数据结构(堆)

书籍简评:<ACM/ICPC 算法训练教程>这本书是余立功主编的,代码来自南京理工大学ACM集训队代码库,所以小编看过之后发现确实很实用,适合集训的时候刷题啊~~,当时是听了集训队final的意见买的,感觉还是不错滴. 相对于其他ACM书籍来说,当然如书名所言,这是一本算法训练书,有着大量的算法实战题目和代码,尽管小编还是发现了些许错误= =,有部分注释的语序习惯也有点不太合我的胃口.实战题目较多是比较水的题,但也正因此才能帮助不少新手入门,个人认为还是一本不错的算法书,当然自学还是需要下不少

2014 ACM/ICPC Asia Regional Guangzhou Online Wang Xifeng&#39;s Little Plot HDU5024

一道好枚举+模拟题目.转换思维视角 这道题是我做的,规模不大N<=100,以为正常DFS搜索,于是傻乎乎的写了起来.各种条件限制模拟过程 但仔细一分析发现对每个点进行全部八个方向的遍历100X100X100^8 .100X100个点,每个点在走的时候8中选择,TLE 于是改为另一个角度: 以符合要求的点为拐弯点,朝两个垂直的方向走,求出最远的距离.这样只要对每个点各个方向的长度知道,组合一下对应的就OK. 避免了每个点深搜. PS:搜索的时候x,y写反了,导致构图出现问题,以后用[dy][dx]

HDU 5014 Number Sequence(2014 ACM/ICPC Asia Regional Xi&#39;an Online) 题解

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5014 Number Sequence Problem Description There is a special number sequence which has n+1 integers. For each number in sequence, we have two rules: ● ai ∈ [0,n] ● ai ≠ aj( i ≠ j ) For sequence a and sequ