并查集的一道比较考想法的题 题意:给你n个点,接着给你n-1条边形成一颗生成树,每条边都有一个权值.求的是以一个点作为特殊点,并求出从此点出发到其他每个点的条件边权的总和最大,条件边权就是:起点到终点经过的权值的最小值. 如果按照最原始的想法来做的话就是枚举每个点作为特殊点,离线dfs再遍历到每个点来计算条件边权总和,最后求一个最大值即可.但是此题点数有20万显然超时,接着想了一下是否可以枚举每个点后,使用数据结构或模拟dp(使用之前的条件边权总和)优化成为log2n,结果并没有什么想法.然而如…
2.解题思路:本题利用欧拉回路存在条件解决.可以将所有的单词看做边,26个字母看做端点,那么本题其实就是问是否存在一条路径,可以到达所有出现过的字符端点.由于本题还要求了两个单词拼在一起的条件是前一个单词的右端点和本单词的左端点一样.所以这是一个有向图.根据结论:有向图的底图(忽略边的方向后的图)必须连通:有向图中最多只能有两个端点的入度不等于出度,且必须是其中一点的入度比出度小1,另一点的入度比出度大1.因此先判断端点是否都连通,再判断每个端点的度数是否满足结论即可. 那么,如何判断连通性呢?…
题意:输入着火点n,求结点1到结点n的所有路径,按字典序输出,要求结点不能重复经过. 分析:用并查集事先判断结点1是否可以到达结点k,否则会超时.dfs即可. #pragma comment(linker, "/STACK:102400000, 102400000") #include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<cmat…
思路: 分别存下每个字符串的首尾字符,以字符为结点,单词看作一条变,就变成了求欧拉回路了,先判断下图是否连通,然后根据欧拉回路的结论:最多只能有两个点的入读不等于初读,而且必须是一个点的出度恰好比入度大1(将它作为起点),另一个的入度比出度大1(将它作为终点): 实现代码: #include<iostream> #include<cstring> using namespace std; ; int f[M]; int in[M],out[M]; int fd(int x) {re…
https://vjudge.net/problem/UVA-1395 题意: 给出一个n结点的图,求苗条度(最大边减最小边的值)尽量小的生成树. 思路: 主要还是克鲁斯卡尔算法,先仍是按权值排序,对于一个连续的边集区间[L,R],如果这些边使得n个点全部连通,则一定存在一个苗条度不超过W[R]-W[L]的生成树.从小到大枚举L,对于每个L,从小到大枚举R. 这道题目我一直超时,最后发现数组开小了,我一直以为数组开小了肯定会出来Runtime error的... #include<iostrea…
https://vjudge.net/problem/UVA-1664 题意: n个城市形成一棵树,每条边有权值C(i,j).任意两个点的容量S(i,j)定义为i与j唯一通路上容量的最小值.找一个点,使得它到其他所有点的容量之和最大. 思路: 做法有点类似于最小生成树的Kruskal算法. 先将边按权值从大到小排列,每次新加入一条边,检查边两段A和B所处并查集的根结点,并通过计算得出谁作为中心点时容量更大.计算过程中需要维护一些东西,sum[i]是以i为中心时的容量之和,cnt[i]是以i为根结…
UVA - 11987 Almost Union-Find I hope you know the beautiful Union-Find structure. In this problem, you’re to implement something similar, but not identical. The data structure you need to write is also a collection of disjoint sets, supporting 3 oper…
传送门 Description I hope you know the beautiful Union-Find structure. In this problem, you’re to implement something similar, but not identical. The data structure you need to write is also a collection of disjoint sets, supporting 3 operations: 1 p q…
UVA 11987 - Almost Union-Find 题目链接 题意:给定一些集合,操作1是合并集合,操作2是把集合中一个元素移动到还有一个集合,操作3输出集合的个数和总和 思路:并查集,关键在于操作2,对于并查集,要去除掉一个结点,假设该结点不是根那就好办了,那么就多开n个结点,每一个结点初始父亲都是它的i + n,这样在移动的时候,就不用操心他是根结点了剩下就是普通的带权并查集了 代码: #include <cstdio> #include <cstring> const…
开始给你n个集合,m种操作,初始集合:{1}, {2}, {3}, … , {n} 操作有三种: 1 xx1 yy1 : 合并xx1与yy1两个集合 2 xx1 yy1 :将xx1元素分离出来合到yy1上 3 xx1 :查询xx1集合的元素个数,和元素所有值总和 并查集,1就是合并两个集合,3要记录两个权值.因为只要祖先的权值,所以Find操作不需要更新权值.  接着就是分离元素了,在这儿我使用映射的方法:开始每个元素都映射自己,接着要删除元素时,我不直接删除元素(因为删除的话可能影响很大),我…