题目链接:点这里,没错,就是这里
【题意】
给你一个有向图,图中的点上可能有棋子,两个人玩这个游戏,每次选择一个棋子,按照图中的方向移动一下棋子,问你是否能先手必胜。棋子可能有多个,多个棋子可能在同一个点。
【分析】
这段时间疯狂的水了水博弈的题,终于不是束手无策了。拿到这个题目第一直觉就是SG。万能的SG啊。果然让我过了。下面来分析。
首先对于每个棋子来说,在有向图中,完全就是个简单博弈。直接求棋子所在点的SG值就行了。但是棋子有多个,这一点也很好想,NIM博弈嘛。然后对于每个棋子直接求它的SG值然后异或一下就可以得到最后的答案了。要注意的一点是最好记忆化搜索一下不然可能超时。
【代码】
#include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<vector> #include<cmath> #include<stdlib.h> #include<time.h> #include<stack> #include<set> #include<map> #include<queue> #include<sstream> using namespace std; #define rep0(i,l,r) for(int i = (l);i < (r);i++) #define rep1(i,l,r) for(int i = (l);i <= (r);i++) #define rep_0(i,r,l) for(int i = (r);i > (l);i--) #define rep_1(i,r,l) for(int i = (r);i >= (l);i--) #define MS0(a) memset(a,0,sizeof(a)) #define MS1(a) memset(a,-1,sizeof(a)) #define MSi(a) memset(a,0x3f,sizeof(a)) #define sin1(a) scanf("%d",&(a)) #define sin2(a,b) scanf("%d%d",&(a),&(b)) #define sll(a) scanf("%lld",&(a)) #define sll2(a,b) scanf("%lld%lld",&(a),&(b)) #define sdo(a) scanf("%lf",&(a)) #define sdo2(a,b) scanf("%lf%lf",&(a),&(b)) #define inf 0x3f3f3f3f #define lson l, m, rt << 1 #define rson m+1, r, rt << 1|1 #define uint unsigned int typedef pair<int,int> PII; #define A first #define B second #define pb push_back #define MK make_pair #define ll long long template<typename T> void read1(T &m) { T x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } m = x*f; } template<typename T> void read2(T &a,T &b) { read1(a); read1(b); } template<typename T> void read3(T &a,T &b,T &c) { read1(a); read1(b); read1(c); } template<typename T> void out(T a) { if(a>9) out(a/10); putchar(a%10+'0'); } template<typename T> void outn(T a) { if(a>9) out(a/10); putchar(a%10+'0'); puts(""); } using namespace std; vector<int>G[1005]; int SG[1005]; int getSG(int x) { if(SG[x]!=-1) return SG[x]; bool vis[1005]; memset(vis,false,sizeof(vis)); for(uint i=0;i<G[x].size();i++) { vis[getSG(G[x][i])]=true; } int t=0; while(vis[t]) t++; return (SG[x]=t); } int main() { // freopen("in.txt","r",stdin); int x; while(sin1(x)!=EOF) { for(int i=0; i<x; i++) { G[i].clear(); int len; read1(len); while(len--) { int t; read1(t); G[i].pb(t); } } memset(SG,-1,sizeof(SG)); int que; while(read1(que),que) { int ans=0; while(que--) { int t; read1(t); ans^=getSG(t); } puts((ans?"WIN":"LOSE")); } } return 0; }