hdu3635Dragon Balls

2024-06-12 17:48
文章标签 balls hdu3635dragon

本文主要是介绍hdu3635Dragon Balls,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

并查集

对于转移次数,开始我自以为想出了一个效率很高的解法,就是在路径压缩的时候统计结点所在的层数,加到该结点的times值里面,也就是这样:



 自己感觉还很良好,因为这样效率和原来几乎差不多,交上去却wa,原来,是没有考虑这样的情况:



如果在结点E或F进行查找并且压缩路径,就会成为这样(以find(e)为例):



这样在这里得到的C B E F的times值都是正确的,但求D的times值时就会得到错误的结果。

这里关键是并查集对应的树的形态的问题,事实上,这里的搜索树形态可以是任意的,而不是第一张图里面的单链形式,因为对于每条链的合并,都可以是在调用根结点时进行的,这时就不涉及路径压缩,于是各种各样形态的图都有可能出现(比如第二张图,可以由dc fe cb ba 的命令得到)。。。

哪怎么办呢?如何得到正确答案又提高效率呢?可行的办法是记录一个结点的根结点,然后在计算的时候把根结点的移动另外加上。。不过我的版本没有这个——我没有用路径压缩,结果实际上慢不了多少。。。额,感觉这句话一说前面说的都变成废话了。。。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int MAX =10005;int last[MAX],amount[MAX],times[MAX],which,all,n,m,move;void make(int n){for(int i=1;i<=n;i++){last[i]=i,amount[i]=1,times[i]=0;}
}int find(int x){if(x==last[x]){which=x;return 0;}int layer=find(last[x]);//times[x]+=layer;//开始的想法,错误的//last[x]=which;//路径压缩return layer+1;
}void un(int a,int b){amount[b]+=amount[a];last[a]=b;
}int main(){int T,a,b,aa,bb,cases=1;char com[20];scanf("%d",&T);while(T--){printf("Case %d:\n",cases++);scanf("%d %d",&n,&m);getchar();make(n);for(int i=0;i<m;i++){scanf("%s",com);if(com[0]=='T'){scanf("%d %d",&a,&b);find(a),aa=which;find(b),bb=which;if(aa!=bb)un(aa,bb);}else if(com[0]=='Q'){scanf("%d",&a);move=find(a);printf("%d %d %d\n",which,amount[which],last[a]==a?0:(move));}}}return 0;
}




这篇关于hdu3635Dragon Balls的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1054912

相关文章

poj 3687 Labeling Balls(拓扑排序)

http://poj.org/problem?id=3687 非常坑的一道题,最后快要绕晕了。。 题意:有N个球,重量分别是1~N,给着n个球贴上标签。输入n,m代表n个球和m条边(a b),代表 标签为a的要比标签为b的轻。最后输出标签1~N对应的重量(注意是重量,而不是轻重关系),还有要注意“ you should output the one with the smallest weig

HDU 3635 Dragon Balls(带权并查集)

题目地址:HDU 3635 加权并查集水题。 用num数组维护该城市有多少龙珠,用times数组维护每个龙珠运输了多少次。num数组在合并的时候维护。times数组由于每个都不一样,所以要在找根的时候递归来全部维护。 最终,x龙珠所在的城市就是x节点所在的根,x结点所在的跟的num数组值是该城市的龙珠数。times[x]为该龙珠运输了多少次。 代码如下: #include <iost

hdu 4611 Balls Rearrangement(数学:推理+模拟)

一道很蛋疼的题 列出几组数据会发现是有规律的 一个数字可能会连续出现多次 虽然发现了规律,但是不知道该怎么写 看了大牛的博客。。。也是醉了 因为一个最小公倍数周期内结果是固定的,所以如果n>lcm,可以优化处理 这道题比较奇葩的地方是用scanf就wa,用cin就过了 代码如下: #include <cstdio>#include <iostream>#include <a

codeforces 553A Kyoya and Colored Balls 组合数学

题意: 有k种球,每种球有a[i]个。现在它们都放到一个袋子里,要求取出来的时候,第i种球完全取出来要在第i+1种球前面。问你有多少种取法。 思路: 比赛时没想出来。。。结果其实是很简单的。 倒过来统计就好了。 假设n = sum(a[i]); 首先先看第k种球,如果先把其中一个球放到最后一个位置,那么剩下的a[k]-1个球就是随便放,则有c[n-1][a[k]-1]种放法。

Poj 3687 Labeling Balls[拓扑排序]

题目链接:点击打开链接 很给力的道题,拓扑排序的应用,算是对TopSort认识更深了吧。 拓扑排序这里不做过多的解释,主要来说这道题的应用。 题目的意思就是给1——N质量的N个球贴标签,要求就是满足要求下的标签小的尽量轻。 没什么深入想,直接TopSort。果断WA,WA的。后来看题,发现了很多的问题。输出的是Label1-LabelN标签的重量。还有很多的问题没有看太清晰。 再看了几

hdu 5570 balls(高效)

题目链接:hdu 5570 balls 代码 #include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 1005;int N, M;double A[maxn][maxn];int main () {while (scanf("%d%d", &N, &M) ==

dp + 计数,1954D - Colored Balls

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 Problem - 1954D - Codeforces 二、解题报告 1、思路分析 本题前置题目: 1953. 你可以工作的最大周数 通过前置题目可以知道如何计算两两不同数对序列的最大长度 我们记最大数量为ma,总数目为N 如果ma > N / 2, 那么划

Dropping Balls(UVA 679)

网址如下: Dropping Balls - UVA 679 - Virtual Judge (vjudge.net) (第三方网站) 二叉树 别说了,我只会模拟,最后用时530ms 结果算法书给出了一个优化的解法: 因为小球要么往左,要么往右,根据到这个点有几个小球可以推断出当前点的状态,根据要求的第几个小球可以推断在这个点有多少个球往左走了,多少个球往右走了 这样可以根据 I

Edu 18 Colored balls -- 题解

目录 Colored Balls: 题目大意: 思路解析: 代码实现: Colored Balls: 题目大意:            思路解析:         我们对于一个数n,如果分组大小超过了 根号n,那么便不可能将n 分为多个组,并且组间差距最大为1.         那么我们只需要找到数组a中最小的n,枚举 1-sqrtn,看其他数是否能满足这样的分组

两次入坑逆向拓扑序(POJ 3687 Labeling Balls and HDU 4857 逃生)

第一次跳坑 POJ 3687 Labeling Balls Description Windy has N balls of distinct weights from 1 unit to N units. Now he tries to label them with 1 to N in such a way that: No two balls share the same label