CodeForces

传送门:CodeForces - 937D 

题意:两人进行一场走棋子的游戏,如果有人无法再继续走下去,那么他就输了。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;
}
原文地址:https://www.cnblogs.com/Mrleon/p/8495705.html