HZNUOJ 2977 宝可梦决战 种族并查集

 原题链接:

https://acm.hznu.edu.cn/OJ/problem.php?id=2977https://acm.hznu.edu.cn/OJ/problem.php?id=2977

Description

俊俊终于打败了深渊法师, 来到了npy的面前。 npy说, 你要跟我玩个游戏, 只有你过关了, 我才会跟你走。他们决定玩宝可梦的游戏。在npy自制的简易宝可梦中,每只宝可梦都有且只有水, 火, 草中的一个属性(水 > 火 > 草 > 水, 其中>表示克制关系), 两只宝可梦对战时, 若存在属性克制, 则效果拔群。现在有n只宝可梦, npy决定, 不告诉俊俊每只宝可梦的具体属性, 只给出m条提示, 每条提示包括两只宝可梦的克制关系。最后俊俊和npy各从池子中抽出一只宝可梦进行对决, 若俊俊胜利了, 则可以带走npy。

聪明的俊俊知道他的胜算并不高, 但是他太想带走npy了。在他的苦苦哀求(死缠烂打)之下, npy被感动了, 决定给俊俊一个特殊技能:比赛开始前, 俊俊可以发动技能, 交换他们两个的宝可梦

Input

第一行两个整数n,m(2 <= n <= 100000, 1 <= m <= 100000), 表示一共有n只宝可梦和m个提示

接下来的m行, 每行给出两个整数x, y(1 <= x, y <= n)。表示宝可梦x克制y

最后一行给出两个整数a, b 分别表示俊俊的宝可梦和npy的宝可梦

数据保证读完所有的提示后, 任意两只宝可梦的克制关系都已知,且不存在克制关系冲突的情况

Output

如果俊俊的宝可梦克制npy的宝可梦, 他就会充满自信的喊一句“wait for me, my dear!”

如果俊俊的宝可梦被克制, 他就会发动技能大喊“change! change! change!”

如果两者的宝可梦属性相同,他就会对充满悬念的战局感到担忧, 说“can I win the game?”

 

请输出俊俊说的话

Sample

input Copy

3 2

1 2

2 3

3 1

output Copy

wait for me, my dear!

解题思路:较基础的种族并查集考察,相较于普通的并查集,这里我们要维护水 > 火 > 草 > 水这个克制关系,因此我们引入d[x]数组来表示该节点和根节点的距离;

我们不妨设根节点以及到根节点的距离%3==0的点为水,到根节点的距离%3==1的点为草(草克水),到根节点的距离%3==2的点为火(火克草)。

这样我们的克制关系可以整理为下图:

 我们可以看出,互相克制的两个宝可梦在%3后的距离差为1,因此判断两个宝可梦a是否克制b的公式即 if(!(d[a]-d[b]-1)%3) 是否相同的公式为 if(!(d[a]-d[b])%3)

除此之外我们还要一个特殊情况:当输入的a和b不在集合中时,应该如何处理

ac代码:

#include <bits/stdc++.h>
using namespace std;
int p[100010],d[100010];
int find(int x)
{
    if(p[x]!=x)
    {
        int t=find(p[x]);
        d[x] +=d[p[x]];
        p[x]=t;
    }
    return p[x];
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n,m;
    cin >> n >> m;
    for (int i=1;i<=n;i++) p[i]=i;
    while (m--)
    {
    int x,y;
    cin >> x >> y;
    int px=find(x),py=find(y);
    if(py!=px) {
        p[px] = py;
        d[px] = d[y] + 1 - d[x];
    }
    }
    int a,b;
    cin >> a >> b;
    a1:
    int px=find(a);
    int py=find(b);
    if(py==px)
    {
        if((d[a]-d[b]-1)%3==0) cout << "wait for me, my dear!";
        else if((d[a]-d[b])%3==0) cout << "can I win the game?";
        else cout << "change! change! change!";
    }else if(px!=py)
    {
        p[px]=py;
        d[px]=d[b]+1-d[a];
        goto a1;
    }
    return 0;
}

 写在最后:建议读者在了解并查集的基础上再来看这篇文章和写这道题,要不然可能会难以理解,本人表达能力欠佳,如有纰漏多多包涵,欢迎批评,感谢qwq

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值