Codeforces 937 D. Sleepy Game(DFS 判断环)
题目链接: Sleepy Game
题意:
Petya and Vasya 在玩移动旗子的游戏, 谁不能移动就输了。 Vasya在订移动计划的时候睡着了, 然后Petya 就想趁着Vasya睡着的时候同时定下策略, 如果可以赢得话输出Win 并输出路径, 如果步数在达到1e6的情况下,就认定为平局, 输出Draw,如果输的话就输出lost。
题解:
这题很容易就可以想到如果图中存在奇数长度的路径从起始点到叶子结点就是Win状态(这里还要注意绕环走的情况,比如说奇数长度的环是可以改变路径的奇偶性的),如果不存在奇数长度的路径但是存在环的话就是Draw,如果都不是就是Lost。写了以后深深地发现自己的DFS是真的挫,如何判断有向图的环@。@! DFS的时候:
res[u][0]==1表示u这个点能从s点偶数路径到达
res[u][1]==1表示u这个点能从s点奇数路径到达
如果dfs到某点发现res的值已经为1就不用再继续下去了,这样就能保证dfs时每个点最多被访问2次。那么如果存在一个点x,使得res[x][1]==1且x的出度为0,那么就是Win的方案。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAX_N = 1e5+9; 4 int res[MAX_N][2],point[MAX_N],num_s,st[MAX_N*4],vis[MAX_N]; 5 vector<int> vec[MAX_N]; 6 int N,M,x; 7 void init() 8 { 9 num_s = 0; 10 memset(st,0,sizeof(st)); 11 memset(vis,0,sizeof(vis)); 12 memset(res,0,sizeof(res)); 13 memset(point,0,sizeof(point)); 14 for(int i=0; i<MAX_N; i++) vec[i].clear(); 15 } 16 bool dfs(int pos,int x) 17 { 18 if(res[pos][x^1] == 1) return false; 19 res[pos][x^1] = 1; 20 st[num_s ++] = pos; 21 if(vec[pos].size() == 0 && res[pos][1]) 22 { 23 return true; 24 } 25 for(int i=0; i<vec[pos].size(); i++) 26 { 27 if(dfs(vec[pos][i],x^1)) return true; 28 } 29 num_s --; 30 return false; 31 } 32 bool cheak(int pos) 33 { 34 vis[pos]=1; 35 bool f=false; 36 for(int i=0; i<vec[pos].size(); i++) 37 { 38 if(vis[vec[pos][i]]==1) f=true; 39 else if(vis[vec[pos][i]]==0) f=cheak(vec[pos][i]); 40 if(f) return true; 41 } 42 vis[pos] = 2; 43 return false; 44 } 45 int main() 46 { 47 cin>>N>>M; 48 init(); 49 for(int i=1; i<=N; i++) 50 { 51 int num,temp; 52 scanf("%d",&num); 53 for(int j=0; j<num; j++) 54 { 55 scanf("%d",&temp); 56 vec[i].push_back(temp); 57 } 58 } 59 int pos; 60 cin>>pos; 61 if(dfs(pos,1)) 62 { 63 cout<<"Win"<<endl; 64 for(int i=0; i<num_s; i++) 65 { 66 printf("%d ",st[i]); 67 } 68 cout<<endl; 69 } 70 else if(cheak(pos)) 71 cout<<"Draw"<<endl; 72 else 73 cout<<"Lose"<<endl; 74 }