Codeforces 936B Sleepy Game BFS+DFS判环

2024-03-30 02:58

本文主要是介绍Codeforces 936B Sleepy Game BFS+DFS判环,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题面

题目链接:传送门

Petya and Vasya arranged a game. The game runs by the following rules. Players have a directed graph consisting of n vertices and m edges. One of the vertices contains a chip. Initially the chip is located at vertex s. Players take turns moving the chip along some edge of the graph. Petya goes first. Player who can’t move the chip loses. If the game lasts for 106 turns the draw is announced.

Vasya was performing big laboratory work in “Spelling and parts of speech” at night before the game, so he fell asleep at the very beginning of the game. Petya decided to take the advantage of this situation and make both Petya’s and Vasya’s moves.

Your task is to help Petya find out if he can win the game or at least draw a tie.

Input
The first line of input contain two integers n and m — the number of vertices and the number of edges in the graph (2 ≤ n ≤ 105, 0 ≤ m ≤ 2·105).

The next n lines contain the information about edges of the graph. i-th line (1 ≤ i ≤ n) contains nonnegative integer ci — number of vertices such that there is an edge from i to these vertices and ci distinct integers ai, j — indices of these vertices (1 ≤ ai, j ≤ n, ai, j ≠ i).

It is guaranteed that the total sum of ci equals to m.

The next line contains index of vertex s — the initial position of the chip (1 ≤ s ≤ n).

Output
If Petya can win print «Win» in the first line. In the next line print numbers v1, v2, …, vk (1 ≤ k ≤ 106) — the sequence of vertices Petya should visit for the winning. Vertex v1 should coincide with s. For i = 1… k - 1 there should be an edge from vi to vi + 1 in the graph. There must be no possible move from vertex vk. The sequence should be such that Petya wins the game.

If Petya can’t win but can draw a tie, print “Draw” in the only line. Otherwise print “Lose”.

题意:A,B两人玩游戏,B睡着了,A来操控棋子。A先走,B后走。若A能走到某处后,轮到B走但无路可走,则A赢了。若两人共走了 106 10 6 步后仍未分出胜负,则为平局。

思路

分析题意,能否使”A走完后B无处可走“,等同于找到一条路径,使这条路径长度为奇数(即有偶数个节点)。
记录两个标记:flag表示是否平局,win表示是否能赢。两者初始值都为false。
先bfs一遍,若搜到的节点没有可达到的点,且此时路径长度为奇数,则将win设为true。
若bfs的路径长已超过 106 10 6 ,则将flag设为true并返回。
bfs完,若flag和win均为false,则说明A无法赢,也无法找到一条路径使它的长度超过 106 10 6 ,此时再dfs一次,判断是否有环路,若有,则A可以平局。
若dfs后发现无环路,则A必输。

代码

#include<stdio.h>
#include<cstring>
#include<vector>
using namespace std;
int read() {int x=0,f=1;char ch=getchar();while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0' && ch<='9') {x=10*x+ch-'0';ch=getchar();}return x*f;
}
const int Size=100001;
vector<int> to[Size];       //vector大法好 存每个点所能到达的节点 
bool vis[Size][2];          //判重数组 
bool flag=false,win=false;  //两种标记 
struct node {int father,x,y,t;/*father:记录队列目前节点的父节点,递归输出时用*/
} w[Size*20];
int n,m,head,tail,last,pos;
void PushQueue(int fx,int x,int y,int t) {  //入队 tail++;w[tail].x=x;w[tail].y=y;w[tail].father=fx;w[tail].t=t;vis[x][y]=true;
}
void bfs(int x) {           //bfs判路径长 PushQueue(0,x,1,0);while(head<tail) {head++;int len=to[w[head].x].size();if(!len) {win=!w[head].y;last=head;if(w[head].t>1e6)   flag=true;if(win) return;}for(int i=len-1; i>=0; i--) {if(!vis[to[w[head].x][i]][!w[head].y]) {PushQueue(head,to[w[head].x][i],!w[head].y,w[head].t+1);}}}
}
void Out(int x) {           //若可以赢,则递归输出节点编号 if(x)   Out(w[x].father);if(x)   printf("%d ",w[x].x);
}
int go[Size];
bool dfs(int x) {           //dfs判环 go[x]=1;int len=to[x].size();for(int i=0; i<len; i++) {if(go[to[x][i]]==1) {return true;} else if(!go[to[x][i]]) {if(dfs(to[x][i]))   return true;    //注意不要写成return dfs(to[x][i]) } else {continue;}}go[x]=-1;return false;
}
int main() {n=read();m=read();for(int i=1; i<=n; i++) {int l=read(),tmp;while(l--) {tmp=read();to[i].push_back(tmp);}}int s=read();bfs(s);if(win) {puts("Win");Out(last);} else if(flag || dfs(s)) {puts("Draw");} else {puts("Lose");}return 0;
}

这篇关于Codeforces 936B Sleepy Game BFS+DFS判环的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/860318

相关文章

hdu1254(嵌套bfs,两次bfs)

/*第一次做这种题感觉很有压力,思路还是有点混乱,总是wa,改了好多次才ac的思路:把箱子的移动当做第一层bfs,队列节点要用到当前箱子坐标(x,y),走的次数step,当前人的weizhi(man_x,man_y),要判断人能否将箱子推到某点时要嵌套第二层bfs(人的移动);代码如下:

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

poj 3050 dfs + set的妙用

题意: 给一个5x5的矩阵,求由多少个由连续6个元素组成的不一样的字符的个数。 解析: dfs + set去重搞定。 代码: #include <iostream>#include <cstdio>#include <set>#include <cstdlib>#include <algorithm>#include <cstring>#include <cm

poj 2195 bfs+有流量限制的最小费用流

题意: 给一张n * m(100 * 100)的图,图中” . " 代表空地, “ M ” 代表人, “ H ” 代表家。 现在,要你安排每个人从他所在的地方移动到家里,每移动一格的消耗是1,求最小的消耗。 人可以移动到家的那一格但是不进去。 解析: 先用bfs搞出每个M与每个H的距离。 然后就是网络流的建图过程了,先抽象出源点s和汇点t。 令源点与每个人相连,容量为1,费用为

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

Codeforces Round #261 (Div. 2)小记

A  XX注意最后输出满足条件,我也不知道为什么写的这么长。 #define X first#define Y secondvector<pair<int , int> > a ;int can(pair<int , int> c){return -1000 <= c.X && c.X <= 1000&& -1000 <= c.Y && c.Y <= 1000 ;}int m

Codeforces Beta Round #47 C凸包 (最终写法)

题意慢慢看。 typedef long long LL ;int cmp(double x){if(fabs(x) < 1e-8) return 0 ;return x > 0 ? 1 : -1 ;}struct point{double x , y ;point(){}point(double _x , double _y):x(_x) , y(_y){}point op

Codeforces Round #113 (Div. 2) B 判断多边形是否在凸包内

题目点击打开链接 凸多边形A, 多边形B, 判断B是否严格在A内。  注意AB有重点 。  将A,B上的点合在一起求凸包,如果凸包上的点是B的某个点,则B肯定不在A内。 或者说B上的某点在凸包的边上则也说明B不严格在A里面。 这个处理有个巧妙的方法,只需在求凸包的时候, <=  改成< 也就是说凸包一条边上的所有点都重复点都记录在凸包里面了。 另外不能去重点。 int

POJ 3057 最大二分匹配+bfs + 二分

SampleInput35 5XXDXXX...XD...XX...DXXXXX5 12XXXXXXXXXXXXX..........DX.XXXXXXXXXXX..........XXXXXXXXXXXXX5 5XDXXXX.X.DXX.XXD.X.XXXXDXSampleOutput321impossible

Codeforces 482B 线段树

求是否存在这样的n个数; m次操作,每次操作就是三个数 l ,r,val          a[l] & a[l+1] &......&a[r] = val 就是区间l---r上的与的值为val 。 也就是意味着区间[L , R] 每个数要执行 | val 操作  最后判断  a[l] & a[l+1] &......&a[r] 是否= val import ja