博弈论——洛谷P6560 [SBCOI2020] 时光的流逝

[SBCOI2020] 时光的流逝

题目背景

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

“嗯,不如我们一起在这个冬天创造最后一段回忆吧。”
“好呀,我们玩个游戏吧......”

题目描述

这个游戏是在一个有向图(不保证无环)上进行的。每轮游戏开始前,她们先在图上选定一个起点和一个终点,并在起点处放上一枚棋子。

然后两人轮流移动棋子,每次可以将棋子按照有向图的方向移动至相邻的点。

如果谁先将棋子移动至终点,那么谁就胜利了。同样,如果谁无法移动了,那么谁就失败了。

两人轮流操作,请问,他们是否有必胜策略呢?

答案为一个整数 01-1,其中 1 表示(先手)有必胜策略,-1 表示后手有必胜策略,0 表示两人均无必胜策略。

输入格式

1行有三个整数 n,m,q ,表示图上有 n 个点, m 条边,一共进行 q 轮游戏。
接下来 m 行,每行输入两个数 ui,vi ,表示 uivi 有一条边。
接下来 q 行,每行两个数 x,y ,表示每轮操作的起点和终点。数据保证起点,终点不同

输出格式

对于每轮游戏,仅输出一个整数 01-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 可以选择走到 46,若走到 4,接下去 B 可以走到终点,故不可取。若选择走到 6,那么 B 只能走到 7,A 可以走到终点。所以 A 有必胜策略。

样例解释 #2

如图,起点为 1,终点为 5 时, A 和 B 会沿着 1231 的顺序轮流走。因为如果谁先走到 4,那么下一个人就可以走到终点。故谁都没有必胜策略。

起点为 4,终点为 3 时,A 先走到 5,B 无路可走,故 B 失败。

数据范围

对于 10% 的数据,保证图是一条链。

对于 50% 的数据,1n1031m2×1031q10

对于 70% 的数据,1n1051m2×1051q10

对于 100% 的数据,1n1051m5×1051q500

思路

首先考虑输出是 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();
}

`

posted @   からし  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示