题意:两人进行一场走棋子的游戏,如果有人无法再继续走下去,那么他就输了。Petya先走,且如果petya的胜负优先级为:WIN>DRAW>LOSE。(即能赢就让他赢,不能赢就尽可能的平局,实在不行就输)
题解:先dfs搜索,开二位数组vis[][]第一维表示到达的位置,第二维用0和1表示是谁走过的(小技巧:活用XOR),如果走到一个出度为0的点且第二维为1,那么就直接输出WIN。如果没有WIN,那么就需要tarjan缩点(一定只要从起点开始缩点,因为不一定所有点都能从起点到达,被坑了N发!!),判断是否成环,如果有环就能平,如果连环都没有那么就一定输。(还有更简单的dfs做法不过当时没想到)
#include <cstdio> #include <algorithm> #include <cstring> const int N=1e5+5; using namespace std; int head[N]; int nx[2*N]; int to[2*N]; int tot=1; int comMap[N]; int comNum; int Stack[N]; int Size; int vis[N]; int dfn[N],low[N]; int n,m; int flag2=0; int vis2[N][3]; int a[N]; int h=1; int NUM[N]; void dfs2(int u,int step){ for(int i=head[u];i;i=nx[i]){ int v=to[i]; if(vis2[v][step^1])continue; vis2[v][step^1]=1; NUM[h++]=v; if(!step&&!a[v]){ flag2=1; printf("Win "); for(int i=0;i<h;i++)printf("%d ",NUM[i]); exit(0); } dfs2(v,step^1); h--; } } void add(int u,int v){ to[tot]=v; nx[tot]=head[u]; head[u]=tot++; } void dfs(int u,int step){ low[u]=dfn[u]=step; vis[u]=1; Stack[++Size]=u; for(int i=head[u];i;i=nx[i]){ if(!vis[to[i]])dfs(to[i],step+1); if(vis[to[i]]==1)low[u]=min(low[u],low[to[i]]); } if(low[u]==dfn[u]){ int v; comNum++; int mem=0; do{ mem++; v=Stack[Size--]; vis[v]=2; comMap[v]=comNum; }while(u!=v); NUM[comNum]=mem; } } void tarjan(int start){ dfs(start,1); } int main(){ scanf("%d %d",&n,&m); for(int u=1;u<=n;u++){ int t; scanf("%d",&t); a[u]=t; while(t--){ int v; scanf("%d",&v); add(u,v); } } int start; scanf("%d",&start); tarjan(start); int flag=0; for(int i=1;i<=comNum;i++){ if(NUM[i]>1){ flag=1; } } NUM[0]=start; dfs2(start,0); if(flag==1)return printf("Draw "),0; if(flag2==0)printf("Lose "); return 0; }