AtCoder 4804 Beginner Contest 167 D Teleporter 思维题

1. 题目描述

1.1. Limit

Time Limit: 2000 ms

Memory Limit: 1024 MB

1.2. Problem Description

The Kingdom of Takahashi has N N N towns, numbered 1 1 1 through N N N.

There is one teleporter in each town. The teleporter in Town i i i ( 1 ≤ i ≤ N ) (1 \leq i \leq N) (1iN) sends you to Town A i A_i Ai.

Takahashi, the king, loves the positive integer K K K. The selfish king wonders what town he will be in if he starts at Town 1 1 1 and uses a teleporter exactly K K K times from there.

Help the king by writing a program that answers this question.


1.3. Input

N N N K K K
A 1   A 2   …   A N A_1\ A_2\ \dots \ A_N A1 A2  AN

1.4. Constraints

2 ≤ N ≤ 2 × 1 0 5 2 \leq N \leq 2 \times 10^5 2N2×105

1 ≤ A i ≤ N 1 \leq A_i \leq N 1AiN

1 ≤ K ≤ 1 0 18 1 \leq K \leq 10^{18} 1K1018


1.5. Output

Print the integer representing the town the king will be in if he starts at Town 1 1 1 and uses a teleporter exactly K K K times from there.


1.6. Sample Input 1

4 5
3 2 4 1

1.7. Sample Output 1

4

If we start at Town 1 1 1 and use the teleporter 5 times, our travel will be as follows: 1 → 3 → 4 → 1 → 3 → 4 1 \to 3 \to 4 \to 1 \to 3 \to 4 134134.

1.8. Sample Input 2

6 727202214173249351
6 5 2 5 3 2

1.9. Sample Output 2

2

1.10. Source

AtCoder 4804 Teleporter


2. 解读

将所有路径使用邻接表进行存储,然后对路径依次进行遍历,将遍历过的节点存储在栈 S t a c k Stack Stack中,找出图中的环路。

在节点入栈前,判断其是否在栈中,若在,则该节点首次出现的位置到栈顶位置之间的节点所连成的边即为我们要找的环路 C C C,求出环路长度 S S S

判断 游走次数 K K K 是否大于图的起点 Q 0 Q_0 Q0 到环路起点 W 0 W_0 W0 的距离 l e n g t h = Q 0 − W 0 length = Q_0 - W_0 length=Q0W0

K > l e n g t h K > length K>length,则输出 S t a c k Stack Stack 中从 0 0 0 开始计数第 Q 0 + ( K − W 0 ) % S Q_0 + (K - W_0) \% S Q0+(KW0)%S 个元素。

K ≤ l e n g t h K \le length Klength,则输出 S t a c k Stack Stack 中从 0 0 0 开始计数第 K K K 个元素。

3. 代码

#include <iostream>
#include <string.h>
#include <vector>
using namespace std;

const int NUM = 2 * 10e5 + 1;
// 存储
long long list[NUM];
// 标志访问
bool visit[NUM];
// 栈存储访问路径
vector<long long> vec;

int main()
{
    // test case
    long long n, k;
    scanf("%lld %lld", &n, &k);
    // 初始化
    memset(list, 0, sizeof(list));
    memset(visit, 0, sizeof(visit));
    // 输入
    for (long long i = 0; i < n; i++) {
        scanf("%lld", &list[i]);
    }
    // 初始化
    long long buffer = 1;
    // 计算
    for (int i = 0; i < n; i++) {
        // 标志访问
        visit[buffer] = 1;
        // 节点入栈
        vec.push_back(buffer);
        // 获取下一个节点
        buffer = list[buffer - 1];
        // 若形成环路
        if (visit[buffer] == 1) {
            break;
        }
    }
    // 在栈中找出环路开始位置
    auto it = find(vec.begin(), vec.end(), buffer);
    // 环路长度
    long long cycleLength = vec.end() - it;
    // 环路开始前的栈深度
    long long stackLength = it - vec.begin();
    // 计算从环路起点开始的位移
    long long posMark;
    if (k > stackLength) {
        // 若存在环路
        posMark = (k - stackLength) % cycleLength;
    } else {
        // 若不存在环路
        posMark = (k - stackLength);
    }
    // 输出
    printf("%lld\n", vec[stackLength + posMark]);
}

联系邮箱:curren_wong@163.com

Github:https://github.com/CurrenWong

欢迎转载/Star/Fork,有问题欢迎通过邮箱交流。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值