Codeforces Gym 101190 NEERC 16 G. Game on Graph(博弈+拓扑)
Gennady and Georgiy are playing interesting game on a directed graph. The graph has n vertices and m arcs, loops are allowed. Gennady and Georgiy have a token placed in one of the graph vertices. Players take turns moving the token along one of the arcs that starts in the vertex the token is currently in. When there is no such arc, then this player loses the game. For each initial position of the token and the player who is moving first, your task is to determine what kind of result the game is going to have. Does it seem to be easy? Not so much. On one side, Gennady is having a lot of fun playing this game, so he wants to play as long as possible. He even prefers a strategy that leads to infinite game to a strategy that makes him a winner. But if he cannot make the game infinite, then he obviously prefers winning to losing. On the other side, Georgiy has a lot of other work, so he does not want to play the game infinitely. Georgiy wants to win the game, but if he cannot win, then he prefers losing game to making it infinite. Both players are playing optimally. Both players know preferences of the other player.
Input
In the first line there are two integers — the number of vertices n (1 ≤ n ≤ 100000) and the number of arcs m (1 ≤ m ≤ 200000). In the next m lines there are two integers a and b on each line, denoting an arc from vertex a to vertex b. Vertices are numbered from 1 to n. Each (a,b) tuple appears at most once.
Output
In the first line print n characters — i-th character should denote the result of the game if Gennady starts in vertex i. In the second line print n characters — i-th character should denote the result of the game if Georgiy starts in vertex i. The result of the game is denoted by “W” if the starting player wins the game, “L” if the starting player loses the game, and “D” (draw) if the game runs infinitely.
题意: 给定有向图,选定起点,每次可以沿着有向图走到下一个点,没有点走的人输。这样很常规的SG图就可以搞定,但是现在加入新规定,A选手如果可以走无限步也算赢。而B选手宁愿输也不愿意走无限步。 现在对于每个点作为起点,输出A做为先手的结果,以及B选手作为先手的结果。
思路: 有向图,而且有环,不能简单的拓扑 :首先我们想一下SG图的概念,如果后续节点有一个为输,那么当前结点就为赢;如果后续节点都为赢,那么当前节点就为输。
对于平局的情况,我们去找A可以平的点,以及B必平的点:
默认每个点都会平,把入度为0的点加入队列,状态为不平,然后从跑队列。对于当前节点,如果是A,当后缀节点有一个的平是,则其是平;如果是B,后缀节点都跑完了,而且都是平,则其是平。其他的都是不平。
对于输赢的情况,我们去找A必输和B可以输的点:
默认每个点都不知道,把入度为0的点加入队列,状态为输,然后跑队列。对于A,如果上面得出它可以平,则平。否则,如果后缀节点有输,则赢。否则输; 对于B,如果上面得出它必须平,则平。否则后缀节点有输,则赢。否则,输。
(666
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mp make_pair
#define A 0
#define B 1
#define fi first
#define se second
#define Lose 0
#define Win 1
using namespace std;
const int maxn=;
int draw[maxn][],vict[maxn][],c[maxn][];
int outd[maxn],tag[maxn],head,tail;
pii q[maxn];
vector<int>G[maxn];
int main()
{
int N,M,u,v,i,j;
scanf("%d%d",&N,&M);
for(i=;i<=M;i++){
scanf("%d%d",&u,&v);
G[v].push_back(u);
outd[u]++;
}
for(i=;i<=N;i++){
draw[i][A]=draw[i][B]=;//默认会平
tag[i]=outd[i];
if(!outd[i]){
q[++head]=mp(i,A); q[++head]=mp(i,B);
draw[i][A]=; draw[i][B]=;//平不了。
}
}
while(tail<head){
pii now=q[++tail];
for(i=;i<G[now.fi].size();i++){
if((now.se==A&&draw[G[now.fi][i]][B])||(now.se==B&&!(--outd[G[now.fi][i]]))){
draw[G[now.fi][i]][now.se^]=;
q[++head]=mp(G[now.fi][i],now.se^);
}
}
}
//平局算完,来算victory。
head=tail=;
for(i=;i<=N;i++){
outd[i]=tag[i];
vict[i][A]=-; vict[i][B]=-; //默认不知道输赢 ,去找必输必赢的点
}
for(i=;i<=N;i++){
for(j=;j<G[i].size();j++){
if(!draw[i][B]) c[G[i][j]][A]++;
if(!draw[i][A]) c[G[i][j]][B]++; //如果非平的点后缀全是赢,则输
}
if(!outd[i]){
vict[i][A]=Lose,q[++head]=mp(i,A);
vict[i][B]=Lose,q[++head]=mp(i,B);
}
}
while(tail<head){
pii now=q[++tail];
for(i=;i<G[now.fi].size();i++){
if(draw[G[now.fi][i]][-now.se]) continue;
if(vict[now.fi][now.se]==Win){
if(!(--c[G[now.fi][i]][-now.se])){
vict[G[now.fi][i]][-now.se]=;
q[++head]=mp(G[now.fi][i],-now.se);
}
}
else if(vict[G[now.fi][i]][-now.se]==-){
vict[G[now.fi][i]][-now.se]=;
q[++head]=mp(G[now.fi][i],-now.se);
}
}
}
for(i=;i<=N;i++) {
if(vict[i][A]==-) vict[i][A]=;
if(vict[i][B]==-) vict[i][B]=;
}
for(j=;j<;j++,puts(""))
for(i=;i<=N;i++) {
if(draw[i][j]) putchar('D');
else if(vict[i][j]) putchar('W');
else putchar('L');
}
return ;
}
Codeforces Gym 101190 NEERC 16 G. Game on Graph(博弈+拓扑)的更多相关文章
- Codeforces Gym 101190 NEERC 16 .D Delight for a Cat (上下界的费用流)
ls是一个特别堕落的小朋友,对于n个连续的小时,他将要么睡觉要么打隔膜,一个小时内他不能既睡觉也打隔膜 ,因此一个小时内他只能选择睡觉或者打隔膜,当然他也必须选择睡觉或打隔膜,对于每一个小时,他选择睡 ...
- Codeforces Gym 101190 NEERC 16 .L List of Primes(递归)
ls特别喜欢素数,他总是喜欢把素数集合的所有子集写下来,并按照一定的顺序和格式.对于每一个子集,集合内 的元素在写下来时是按照升序排序的,对于若干个集合,则以集合元素之和作为第一关键字,集合的字典序作 ...
- Codeforces Gym 101190M Mole Tunnels - 费用流
题目传送门 传送门 题目大意 $m$只鼹鼠有$n$个巢穴,$n - 1$条长度为$1$的通道将它们连通且第$i(i > 1)$个巢穴与第$\left\lfloor \frac{i}{2}\rig ...
- Codeforces Gym 101623A - 动态规划
题目传送门 传送门 题目大意 给定一个长度为$n$的序列,要求划分成最少的段数,然后将这些段排序使得新序列单调不减. 考虑将相邻的相等的数缩成一个数. 假设没有分成了$n$段,考虑最少能够减少多少划分 ...
- Codeforces GYM 100876 J - Buying roads 题解
Codeforces GYM 100876 J - Buying roads 题解 才不是因为有了图床来测试一下呢,哼( 题意 给你\(N\)个点,\(M\)条带权边的无向图,选出\(K\)条边,使得 ...
- CF Manthan, Codefest 16 G. Yash And Trees 线段树+bitset
题目链接:http://codeforces.com/problemset/problem/633/G 大意是一棵树两种操作,第一种是某一节点子树所有值+v,第二种问子树中节点模m出现了多少种m以内的 ...
- Codeforces Gym 101252D&&floyd判圈算法学习笔记
一句话题意:x0=1,xi+1=(Axi+xi%B)%C,如果x序列中存在最早的两个相同的元素,输出第二次出现的位置,若在2e7内无解则输出-1. 题解:都不到100天就AFO了才来学这floyd判圈 ...
- Codeforces Round #547 (Div. 3) G 贪心
https://codeforces.com/contest/1141/problem/G 题意 在一棵有n个点的树上给边染色,连在同一个点上的边颜色不能相同,除非舍弃掉这个点,问最少需要多少种颜色来 ...
- 【Codeforces Gym 100725K】Key Insertion
Codeforces Gym 100725K 题意:给定一个初始全0的序列,然后给\(n\)个查询,每一次调用\(Insert(L_i,i)\),其中\(Insert(L,K)\)表示在第L位插入K, ...
随机推荐
- hdu 2602 - Bone Collector(01背包)解题报告
Bone Collector Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- 效率提升最重要的原则 - Doing one thing at a time
前段时间流行的时间管理方法 - url=NotLrz-4f4eCgENFAECrXNw88mSLoJ2Rc2MrkP4aes1yQvPjNQRlmdYcbz9oP9U8JoBzJeY-DSUhhInx ...
- request 解决中文乱码问题
package request; import java.io.IOException;import javax.servlet.ServletException;import javax.servl ...
- 请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配
// test20.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include< ...
- 【特征匹配】SIFT原理与C源代码剖析
相关: KD树+BBF算法解析 SURF原理与源代码解析 SIFT的原理已经有非常多大牛的博客上做了解析,本文重点将以Rob Hess等人用C实现的代码做解析,结合代码SIFT原理会更easy理解.一 ...
- MySQL5.7.18 备份、Mysqldump,mysqlpump,xtrabackup,innobackupex 全量,增量备份,数据导入导出
粗略介绍冷备,热备,温暖,及Mysqldump,mysqlpump,xtrabackup,innobackupex 全量,增量备份 --备份的目的 灾难恢复:意外情况下(如服务器宕机.磁盘损坏等)对损 ...
- Appium python Uiautomator2 多进程问题
appium更新uiautomator后可以获取tost了,大家都尝试,课程中也讲解了,但是这些跑的时候都在单机上,当我们多机并发的时候会出现一个端口问题,因为我们appium最后会调用uiautom ...
- 深入Asyncio(五)Event Loop
Event Loop loop除了处理协程间的切换与结束时的异常捕捉,还要监听socket和文件描述符.先做个小测试: >>> import asyncio >>> ...
- EasyPusher华为手机直播推流硬编码[OMX.IMG.TOPAZ.Encoder] failed to set input port definition parameters.
EasyPusher作为一款RTSP推送利器, 配合EasyDarwin开源流媒体服务器,在发布伊始,很快获得了广大人民群众的一致好评. 但是也有一些用户反映: EasyPusher在我的华为手机上会 ...
- Jaccard Similarity and Shingling
https://www.cs.utah.edu/~jeffp/teaching/cs5955/L4-Jaccard+Shingle.pdf https://www.cs.utah.edu/~jeffp ...