天天看點

一本通1665【例 3】移棋子遊戲

1665:【例 3】移棋子遊戲

時間限制: 1000 ms         記憶體限制: 524288 KB

【題目描述】

給定一個有 N 個節點的有向無環圖,圖中某些節點上有棋子,兩名玩家交替移動棋子。

玩家每一步可将任意一顆棋子沿一條有向邊移動到另一個點,無法移動者輸掉遊戲。

對于給定的圖和棋子初始位置,雙方都會采取最優的行動,詢問先手必勝還是先手必敗。

【輸入】

第一行,三個整數 N,M,K, N 表示圖中節點總數, M 表示圖中邊的條數, K 表示棋子的個數。

接下來 M 行,每行兩個整數 X,Y 表示有一條邊從 X 出發指向 Y。

接下來一行, K 個空格間隔的整數,表示初始時,棋子所在的節點編号。

【輸出】

若先手勝,輸出 win,否則輸出 lose。

【輸入樣例】

6 8 4
2 1
2 4
1 4
1 5
4 5
1 3
3 5
3 6
1 2 4 6      

【輸出樣例】

win      

【提示】

資料範圍與提示:

對于全部資料,N≤2000,M≤6000,1≤K≤N。

sol:圖中已經給出了一張拓撲圖,每個點走到不能走都有若幹個不同的步數,

暴力dfs 就可以求出SG值,詢問的時候異或起來就好了

#include <bits/stdc++.h>
using namespace std;
typedef int ll;
inline ll read()
{
    ll s=0;
    bool f=0;
    char ch=' ';
    while(!isdigit(ch))
    {
        f|=(ch=='-'); ch=getchar();
    }
    while(isdigit(ch))
    {
        s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
    }
    return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
    if(x<0)
    {
        putchar('-'); x=-x;
    }
    if(x<10)
    {
        putchar(x+'0'); return;
    }
    write(x/10);
    putchar((x%10)+'0');
    return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const int N=2005,M=6005;
int n,m,k;
int SG[N];
namespace Picture
{
    int tot=0,Next[M],to[M],head[N];
    inline void add(int x,int y)
    {
        Next[++tot]=head[x];
        to[tot]=y;
        head[x]=tot;
    }
    bool Arr[N];
    inline void dfs(int x)
    {
        if(Arr[x]) return;
        Arr[x]=1;
        int i,Up=0;
        bool Mark[N]={0};
        for(i=head[x];i;i=Next[i])
        {
            dfs(to[i]);
            Up=max(Up,SG[to[i]]);
            Mark[SG[to[i]]]=1;
        }
        for(i=0;i<=Up+1;i++) if(!Mark[i])
        {
            SG[x]=i; break;
        }
    }
    inline void GetSG()
    {
        int i;
        for(i=1;i<=n;i++) if(!Arr[i]) dfs(i);
        return;
    }
}
#define Pc Picture
int main()
{
    int i,ans=0;
    R(n); R(m); R(k);
    for(i=1;i<=m;i++)
    {
        int x=read(),y=read();
        Pc::add(x,y);
    }
    Pc::GetSG();
    for(i=1;i<=k;i++) ans^=SG[read()];
    (ans)?puts("win"):puts("lose");
    return 0;
}
/*
input
6 8 4
2 1
2 4
1 4
1 5
4 5
1 3
3 5
3 6
1 2 4 6
output
win
*/      

View Code

轉載于:https://www.cnblogs.com/gaojunonly1/p/10554640.html