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 }

原文地址:https://www.cnblogs.com/doggod/p/8496100.html

时间: 2024-10-12 02:39:49

Codeforces 937 D. Sleepy Game(DFS 判断环)的相关文章

CodeForces 937D 936B Sleepy Game 有向图判环,拆点,DFS

题意: 一种游戏,2个人轮流控制棋子在一块有向图上移动,每次移动一条边,不能移动的人为输,无限循环则为平局,棋子初始位置为$S$ 现在有一个人可以同时控制两个玩家,问是否能使得第一个人必胜,并输出一个解,否则判断是否能平局 题解: 看到这个题首先我想到了强连通分量,但是事实证明求出强连通分量,缩点对解决问题没有什么帮助.... 能写一些看似正确的算法,但其实是假算法来的.. ........... 所以应该先分析策略,肯定是能赢就赢,不能赢就求平局,最后才算输 平局很好判断,有向图上,从$S$点

Codeforces 711 D. Directed Roads (DFS判环)

题目链接:http://codeforces.com/problemset/problem/711/D 给你一个n个节点n条边的有向图,可以把一条边反向,现在问有多少种方式可以使这个图没有环. 每个连通量必然有一个环,dfs的时候算出连通量中点的个数y,算出连通量的环中点的个数x,所以这个连通量不成环的答案是2^(y - x) * (2^x - 2). 最后每个连通量的答案相乘即可. 1 //#pragma comment(linker, "/STACK:102400000, 102400000

[bzoj 1064][NOI2008]假面舞会(dfs判断环)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1064 分析: 如果a看到b,则a->b 那么: 1.如果图中有环,则说明这个环的长度肯定是答案的倍数.所以最大种类数=所有环的长度的gcd,最小种类数=所有环的长度的公约数中>=3的最小数 2.如果图中没有环且都是单独的长链,那么最大种类数=每个联通图中最长链的和,最小种类数=3(如果没有则-1) 3.要考虑一种特殊情况:a->b->c->d a->e-&g

【dfs判负环】BZOJ1489: [HNOI2009]最小圈

Description 找出一个平均边权最小的圈. Solution 经典问题,二分答案判断有无负环. 但数据范围大,普通spfa会超时,于是用dfs判负环(快多了). 思路是dis设为0,枚举每个点u,如果d(u)+w<d(v)就搜v,如果搜到的节点曾搜到过说明找到了负环. 感慨一下dfs真是神奇. Code 1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespac

CodeForces - 383C Propagating tree(dfs + 线段树)

题目大意: 给出一棵树,树上每个节点都有权值,然后有两个操作. 1 x val 在结点x上加上一个值val,x的儿子加上 -val,x的儿子的儿子加上 - (-val),以此类推. 2 x 问x节点的值. 思路分析: 每个节点上加值都是给自己的儿子节点加,而且这个是颗树. 比如样例上的,如果你给node 1加一个值,那么五个节点都加. 再给node 2加个值,2的儿子节点也加了,之前给1加的值也要加到2号节点的儿子. 所以你会发现节点的儿子会存在一个从属的关系. 这样的话,我们可以把所有节点从新

Codeforces --- 982C Cut &#39;em all! DFS加贪心

题目链接: https://cn.vjudge.net/problem/1576783/origin 输入输出: ExamplesinputCopy42 44 13 1outputCopy1inputCopy31 21 3outputCopy-1inputCopy107 18 48 104 76 59 33 52 102 5outputCopy4inputCopy21 2outputCopy0NoteIn the first example you can remove the edge bet

LeetCode 287. Find the Duplicate Number (python 判断环,时间复杂度O(n))

LeetCode 287. Find the Duplicate Number 暴力解法 时间 O(nlog(n)),空间O(n),按题目中Note"只用O(1)的空间",照理是过不了的,但是可能判题并没有卡空间复杂度,所以也能AC. class Solution: # 基本思路为,将第一次出现的数字 def findDuplicate(self, nums: List[int]) -> int: s = set() for i in nums: a = i in s if a

CodeForces 711D Directed Roads (DFS判环+计数)

题意:给定一个有向图,然后你可能改变某一些边的方向,然后就形成一种新图,让你求最多有多少种无环图. 析:假设这个图中没有环,那么有多少种呢?也就是说每一边都有两种放法,一共有2^x种,x是边数,那么如果有环呢?假设x是这个连通块的边数, y是这个环的边数,那么就一共有2^x * (2 ^ y - 2) 种,减去这两种就是一边也不变,和所有的边都就变,这样就形成环了. 那么怎么计算呢?这个题的边很特殊,所以我们可以利用这个特征,我们在每个连通块时,用vis记录一下开始的父结点,用cnt记录每一个到

CF 936B Sleepy Game(判环+BFS)

题目链接:http://codeforces.com/problemset/problem/936/B 题目: Petya and Vasya arranged a game. The game runs by the following rules. Players have a directed graph consisting of n vertices and medges. One of the vertices contains a chip. Initially the chip