并查集。
这是我第一次见到需要改动find函数的并查集题目,对并查集有了更深入的认识。
每次移动后遍历改变转移次数必然超时,无论是所有节点全部遍历还是用set优化一下。
每个并查集都必有p[u] = v,然后想到是否可以仅改变tra_num[u]的值,在纸上画了画确实可以。每次把tra_num[u]加1,其实每个根节点只能作为根节点移动一次,剩下的移动均是作为非根节点移动的,最后统计一个龙珠转移过几次时候find一次,途中更新当前龙珠的tra_num为本身加上父龙珠的tra_num。
这题用cin,cout会TLE。至于为什么需要getchar(),看这里。
#include <iostream>
#include <stdio.h>
using namespace std;
const int MAX_N = 10000 + 100;
int t, n, m, tra_num[MAX_N], balls_num[MAX_N], p[MAX_N];
int _find(int x)
{
if(p[x] == x)
return x;
else
{
int temp = p[x];
p[x] = _find(p[x]);
tra_num[x] += tra_num[temp];
return p[x];
}
}
int main()
{
scanf("%d", &t);
int cnt = 0;
while(t--)
{
printf("Case %d:\n", ++cnt);
char q;
int a, b, u, v;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
{
p[i] = i;
tra_num[i] = 0;
balls_num[i] = 1;
}
for(int i = 0;i < m;i++)
{
getchar();
scanf("%c", &q);
if(q == 'T')
{
scanf("%d%d", &a, &b);
u = _find(a);
v = _find(b);
if(u != v)
{
p[u] = v;
tra_num[u]++;
balls_num[v] += balls_num[u];
balls_num[u] = 0;
}
}
else if(q == 'Q')
{
scanf("%d", &a);
u = _find(a);
printf("%d %d %d\n", u, balls_num[u], tra_num[a]);
}
}
}
return 0;
}
本文介绍了解决HDU3635 DragonBalls问题的方法,采用了一种特殊的并查集实现方式。通过修改find函数来记录龙珠的转移次数,避免了遍历所有节点所带来的超时问题。
11万+

被折叠的 条评论
为什么被折叠?



