团体天梯练习 L2-040 哲哲打游戏

发布时间 2023-04-20 15:22:07作者: Amαdeus

L2-040 哲哲打游戏

哲哲是一位硬核游戏玩家。最近一款名叫《达诺达诺》的新游戏刚刚上市,哲哲自然要快速攻略游戏,守护硬核游戏玩家的一切!

为简化模型,我们不妨假设游戏有 \(N\) 个剧情点,通过游戏里不同的操作或选择可以从某个剧情点去往另外一个剧情点。此外,游戏还设置了一些存档,在某个剧情点可以将玩家的游戏进度保存在一个档位上,读取存档后可以回到剧情点,重新进行操作或者选择,到达不同的剧情点。

为了追踪硬核游戏玩家哲哲的攻略进度,你打算写一个程序来完成这个工作。假设你已经知道了游戏的全部剧情点和流程,以及哲哲的游戏操作,请你输出哲哲的游戏进度。

输入格式:

输入第一行是两个正整数 \(N\)\(M\) ( \(1≤N,M≤10^{5}\) ),表示总共有 \(N\) 个剧情点,哲哲有 \(M\) 个游戏操作。

接下来的 \(N\) 行,每行对应一个剧情点的发展设定。第 \(i\) 行的第一个数字是 \(K_{i}\) ,表示剧情点 \(i\) 通过一些操作或选择能去往下面 \(K_{i}\) 个剧情点;接下来有 \(K_{i}\) 个数字,第 \(k\) 个数字表示做第 \(k\) 个操作或选择可以去往的剧情点编号。

最后有 \(M\) 行,每行第一个数字是 \(0、1\)\(2\) ,分别表示:

\(0\) 表示哲哲做出了某个操作或选择,后面紧接着一个数字 \(j\) ,表示哲哲在当前剧情点做出了第 \(j\) 个选择。我们保证哲哲的选择永远是合法的。
\(1\) 表示哲哲进行了一次存档,后面紧接着是一个数字 \(j\) ,表示存档放在了第 \(j\) 个档位上。
\(2\) 表示哲哲进行了一次读取存档的操作,后面紧接着是一个数字 \(j\) ,表示读取了放在第 \(j\) 个位置的存档。
约定:所有操作或选择以及剧情点编号都从 \(1\) 号开始。存档的档位不超过 \(100\) 个,编号也从 \(1\) 开始。游戏默认从 \(1\) 号剧情点开始。总的选项数(即 \(∑K_{i}\) )不超过 \(10^{6}\)

输出格式:

对于每个 \(1\)(即存档)操作,在一行中输出存档的剧情点编号。

最后一行输出哲哲最后到达的剧情点编号。

输入样例:

10 11
3 2 3 4
1 6
3 4 7 5
1 3
1 9
2 3 5
3 1 8 5
1 9
2 8 10
0
1 1
0 3
0 1
1 2
0 2
0 2
2 2
0 3
0 1
1 1
0 2

输出样例:

1
3
9
10

样例解释:

简单给出样例中经过的剧情点顺序:

\(1 -> 4 -> 3 -> 7 -> 8 -> 3 -> 5 -> 9 -> 10\)

档位 \(1\) 开始存的是 \(1\) 号剧情点;档位 \(2\) 存的是 \(3\) 号剧情点;档位 \(1\) 后来又存了 \(9\) 号剧情点。



解题思路

这道题表面上像是有关图的题目,但实际上只是披着图论的外皮而已。记录每个节点可以直接到达那些节点,这个只需要用 \(vector\) 建一个领接表就行,由于题中的询问下标是从 \(1\) 开始的,所以在每次放入领接的节点时,现在当前的 \(vector\) 中放一个 \(-1\)。定义一个数组存放存档的点,题目中给出的操作一定合法,按照题目的要求进行模拟,最后输出答案即可。

/*   一切都是命运石之门的选择  El Psy Kongroo  */
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<functional>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
typedef pair<double, double> pdd;
typedef pair<string, int> psi;
//typedef __int128 int128;
#define PI acos(-1.0)
#define x first
#define y second
//int dx[4] = {1, -1, 0, 0};
//int dy[4] = {0, 0, 1, -1};
const int inf = 0x3f3f3f3f, mod = 1e9 + 7;


const int N = 1e5 + 10;
int n, m;
vector<int> e[N];
int point[N];     //存储存档点
vector<int> res;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);

    cin >> n >> m;
    for(int i = 1; i <= n; i ++ ){
        e[i].push_back(-1);
        int k; cin >> k;
        while(k -- ){
            int x; cin >> x;
            e[i].push_back(x);
        }
    }

    int u = 1;
    while(m -- ){
        int op, x; cin >> op >> x;
        if(op == 0){
            u = e[u][x];
        }else if(op == 1){
            point[x] = u;
            res.push_back(u);
        }else{
            u = point[x];
        }
    }

    for(auto &x : res) cout << x << endl;
    cout << u;

    return 0;
}