题意:
就是给你n个点m条边,然后给你一个初始点st,和一个好点ed。小A和小B轮流操作,小B先操作。如果现在在a点,那么小B可以让一条和a点相连的边删掉。如果现在在a点,那么小A可以选择一条边走过去,并且删去这条边。现在问你当两个人都没法操作的时候,小A是否可以经过好点ed。
思考:
- 刚开始看完,发现点的数量很小。然后画了画图发现,如果从a能走到b的话,要么a和b之间有两条边,要么可以从a走到好点,也就是小B必须删去这条边,所以我可以走a走到b。其实不然,下面这个图就卡死了。
这个图完全可以从st走到ed,但是我第一次像的就不可以。 - 但是这个想法就错了一点,就是一个点a可以走到b的话,要么a和b有两条边。要么a可以走到一个必胜点,必胜点就代表这个点可以经过好点ed。所以小B要砍断走向必胜点的,那么a就可以走到b了。但是我一想既然要预处理出来必胜点的话,我直接倒着推就好了,就是先从ed点往外边走,如果一个点可以有两条边走到必胜点,那么这个点也是必胜点。因为小B不管怎么删,我都可以走到必胜点。
- 当时我还有点困惑的是,比如在某个点的时候,为啥我就让小B先操作呢?因为既然你在某个点了,要么是初始点,要么是小A走过来的,所以正好该小B操作。还有就是想着会不会一个点入队多次呢?有环之类的,但是其实没有,因为进来的都是必胜点,既然是必胜点了,就肯定把别人更新了,如果再放一次就多更新别人了也。
- 所以这个题和之前做的都差不多,就是从已知的状态开始往前推,推着推着就把初始点的状态推出来了。牛客多校-Z-Game on grid。
代码:
#include<bits/stdc++.h>
#define int long long
#define pb push_back
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 110,M = 110;
int T,n,m;
int vis[N];
int flag[N];
int st,ed;
vector<int > e[N];
bool solve()
{
queue<int > q;
q.push(ed);
vis[ed] = 2;
while(q.size())
{
auto now = q.front();
q.pop();
if(flag[now]) continue;
flag[now] = 1;
for(auto spot:e[now])
{
if(vis[now]>=2) vis[spot]++;
}
for(auto spot:e[now])
{
if(vis[spot]>=2) q.push(spot);
}
}
return vis[st]>=2;
}
signed main()
{
IOS;
cin>>T;
while(T--)
{
cin>>n>>m>>st>>ed;
for(int i=1;i<=n;i++)
{
e[i].clear();
flag[i] = vis[i] = 0;
}
for(int i=1;i<=m;i++)
{
int a,b;
cin>>a>>b;
e[a].pb(b);
e[b].pb(a);
}
solve()?cout<<"Join Player\n":cout<<"Cut Player\n";
}
return 0;
}
总结:
多多思考,多想想以前的模型。