博弈论——洛谷P6560 [SBCOI2020] 时光的流逝
[SBCOI2020] 时光的流逝
题目背景
时间一分一秒的过着,伴随着雪一同消融在了这个冬天,
或许,要是时光能停留在这一刻,该有多好啊。
......
“这是...我在这个小镇的最后一个冬天了吧。”
“嗯,你可不能这辈子都呆在这个小镇吧。外面的世界很大呢,很大很大...”
“唔...外面的世界...突然有点期待呢!”
“总有一天,你会走得很远很远。以后你可不要忘记这个小镇那。”
“不会的,至少...这里曾经是我最快乐的一段回忆呢!你也一定不要忘记我呀。”
“你看,这雪花。传说,每当世界上有一份思念,便会化成一片雪花在这里飘落。”
“那...以后你可一定要找到我的那片雪花啊......”

“嗯,不如我们一起在这个冬天创造最后一段回忆吧。”
“好呀,我们玩个游戏吧......”
题目描述
这个游戏是在一个有向图(不保证无环)上进行的。每轮游戏开始前,她们先在图上选定一个起点和一个终点,并在起点处放上一枚棋子。
然后两人轮流移动棋子,每次可以将棋子按照有向图的方向移动至相邻的点。
如果谁先将棋子移动至终点,那么谁就胜利了。同样,如果谁无法移动了,那么谁就失败了。
两人轮流操作,请问,他们是否有必胜策略呢?
答案为一个整数 0 或 1 或 -1,其中 1 表示(先手)有必胜策略,-1 表示后手有必胜策略,0 表示两人均无必胜策略。
输入格式
第\(\text{1}\)行有三个整数 \(n,m,q\) ,表示图上有 \(n\) 个点, \(m\) 条边,一共进行 \(q\) 轮游戏。
接下来 \(m\) 行,每行输入两个数 \(u_i,v_i\) ,表示 \(u_i\) 到 \(v_i\) 有一条边。
接下来 \(q\) 行,每行两个数 \(x,y\) ,表示每轮操作的起点和终点。数据保证起点,终点不同
输出格式
对于每轮游戏,仅输出一个整数 0 或 1 或 -1,其中 1 表示先手有必胜策略,-1 表示后手有必胜策略,0 表示两人均无必胜策略。
样例 #1
样例输入 #1
7 7 1
1 2
2 3
3 4
4 5
3 6
7 5
6 7
1 5
样例输出 #1
1
样例 #2
样例输入 #2
5 5 2
1 2
2 3
3 1
3 4
4 5
1 5
4 3
样例输出 #2
0
1
提示
样例解释 \(#1\)

为描述题意,假设两人为 A(先手)和 B
如图,A 先走,走到 \(2\),B 走到 \(3\),接下去 A 可以选择走到 \(4\) 或 \(6\),若走到 \(4\),接下去 B 可以走到终点,故不可取。若选择走到 \(6\),那么 B 只能走到 \(7\),A 可以走到终点。所以 A 有必胜策略。
样例解释 \(#2\)

如图,起点为 \(1\),终点为 \(5\) 时, A 和 B 会沿着 \(1-2-3-1\) 的顺序轮流走。因为如果谁先走到 \(4\),那么下一个人就可以走到终点。故谁都没有必胜策略。
起点为 \(4\),终点为 \(3\) 时,A 先走到 \(5\),B 无路可走,故 B 失败。
数据范围
对于 \(10\%\) 的数据,保证图是一条链。
对于 \(50\%\) 的数据,\(1\leq n\leq 10^3\),\(1\leq m\leq 2\times10^3\),\(1\leq q\leq 10\)。
对于 \(70\%\) 的数据,\(1\leq n\leq 10^5\),\(1\leq m\leq 2\times10^5\),\(1\leq q\leq 10\)。
对于 \(100\%\) 的数据,\(1\leq n\leq 10^5\),\(1\leq m\leq 5\times10^5\),\(1\leq q\leq 500\)。
思路
首先考虑输出是 \(0\) 的情况,对于当前的人必输,所以控制对方呆在循环之中,此时的答案是 \(0\),起点如果在距离终点 \(1\) 的位置那么先手必胜,所以假设终点处是必败(不存在起点等于终点的情况),\(st[ed]\) 为 \(-1\),如果有人无法移动,那么这个人输,在有向图上无法移动,也就是出度为 \(0\),那么先将出度为 \(0\) 的点和终点存入队列,跑拓扑排序,如果上一个节点是必败,那么这个点无论是不是在环内,一定是必胜是状态,如果上一个点是必胜的状态,这个点不在环内的话就是必输状态,但如果这个点在环内,那么他的状态就不能现在确定,要通过其他的点来判断或者 \(st[x]=0\)。至此,所有点的状态都确定了,直接输出就行,代码如下。
`
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
int n, m, q;
vector<int> g[N];
int ru[N];
int st[N], now[N];
void solve()
{
cin >> n >> m >> q;
while (m --)
{
int a, b;
cin >> a >> b;
g[b].push_back(a);
ru[a] ++;
}
while (q --)
{
int be, ed;
cin >> be >> ed;
queue<int> qu;
for (int i = 1; i <= n; i ++)
{
now[i] = ru[i];
if (!now[i] || i == ed)
{
st[i] = -1;
qu.push(i);
}
else st[i] = 0;
}
while (qu.size())
{
int it = qu.front();
qu.pop();
for (auto x : g[it])
{
if (!st[x])
{
now[x] --;
if (st[it] == -1)
{
st[x] = 1;
qu.push(x);
}
else if (!now[x])
{
st[x] = -1;
qu.push(x);
}
}
}
}
cout << st[be] << "\n";
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
solve();
}
`

浙公网安备 33010602011771号