题目大意:有一个n个点的图,有一个人从s要走到t,在每走一步之前要删除当前点的一个邻边,问能否到达t点
思路:我们不妨从后向前推,如果有一条边能到终点,那么这个点如果到终点必须至少有两条路,那么这样的点就被成为胜利点,如果要在上一层再找到这样的胜利点,就需要下次的点至少有两条边连接上层的某个点,所以只需要从终点开始bfs遍历所有胜利点,同时用队列维护所有上一层的胜利点
#include<bits/stdc++.h>
using namespace std;
const int N = 105, mod = 998244353;
int b[N], cnt[N];
vector<int>g[N];
bool vis[N];
int n, m, s, t;
bool flag = 0;
void bfs()
{
queue<int>q;
q.push(t);
while (!q.empty())
{
int u = q.front();
q.pop();
vis[u] = 1;
if (u == s)//成功到了起点
{
flag = 1;
return;
}
for (int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
if (!vis[v] )
{
cnt[v]++;//给上一层的点的计数+1
if(cnt[v]==2)
q.push(v);//如果计数大于等于2,就把下个点放入队列
}
}
}
}
int main()
{
int tt;
cin >> tt;
while (tt--)
{
flag = 0;
scanf("%d%d%d%d", &n, &m, &s, &t);
for (int i = 1; i <= m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);//邻接表存图
}
bfs();
if (!flag)
{
printf("Cut Player\n");
}
else
{
printf("Join Player\n");
}
for (int i = 1; i<= n; i++)
{
g[i].clear();
vis[i] = 0;
cnt[i] = 0;
}
}
return 0;
}