香浓切换游戏的变体规则如下:
给定有重边的无向图
G
=
(
V
,
E
)
G=(V,E)
G=(V,E), 和两个点
s
,
t
∈
V
s,t \in V
s,t∈V。 最初在
s
s
s 点上有一个令牌。两个玩家
J
o
i
n
P
l
a
y
e
r
Join\ Player
Join Player 和
C
u
t
P
l
a
y
e
r
Cut\ Player
Cut Player 轮流进行以下操作,Cut Player先手:
考虑,若当前只有一条路可以走向终点,那么Cut Player 就可以删去这一条路获得胜利。
而当前选择
>
1
>1
>1 可以走向终点时,Cut Player只能删去一条,还可以继续走。
那么答案就很明晰了,选择一条路,若其中的每一个节点都有超过一种方案能到达终点,则Join Player获胜,反之Cut Player获胜。
由于在图上进行操作,我们考虑倒着枚举,从终点开始遍历,如果从终点可以到达一个节点两次即以上则它可以继续向前,表明该点是可以到达终点的,如果能到达起点,则存在上面说明的路径。
注意:终点不可以通过多次,否则会死循环。
#include
using namespace std;
const int N=105;
vector<int> v[N];
int b[N];
int n,m,s,t,T;
void dfs(int x)
{
b[x]++;
if(b[x]!=2) //若小于2,则无法通过,若大于2,则已经通过
return;
for(int i=0;i<v[x].size();i++)
dfs(v[x][i]);
}
int main()
{
// freopen("1.txt","r",stdin);
// freopen("2.txt","w",stdout);
cin>>T;
while(T--)
{
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=n;i++)
v[i].clear(),b[i]=0;
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
b[t]=1; //终点不允许通过多次
dfs(t);
// for(int i=1;i<=n;i++)
// cout<
if(b[s]>=2) //存在路径
puts("Join Player");
else
puts("Cut Player");
}
}