转载请注明出处谢谢:blog.csdn.net/vmurder/article/details/42968425
诶那个什么94.net这篇题解你要是转载别删出处了谢谢。。。
我再处理一下嘿嘿。blog。csdn。net|vmurder|article|details|42968425
。是.
|是/
做个实验:看看它的转载机制会不会把代码都删除
#include <cstdio>
using namespace std;
int main()
{
puts("blog.csdn.net/vmurder/article/details/42968425");
}
嗯,这是一道原创题。
然后下面贴的是我当时写的题解。
本来以为在BZOJ上面晒一段时间可以有人去花时间想一想这道题。
但是貌似我想多了。。。
{
这道题显然是一道博弈题,然后因为环断了一个点,所以不妨先把它处理成一条链。这道题我对于数据规定了一种性质:任意两条边不相交。这样就大有可做了。
首先我们思考,从起点出发,那么因为每到一个点,之前的点就都走过了,所以现在无法通过边回头,那么也就是说,当总点数(别忘了刨去那一个断点)是奇数的时候,直接从1出发,就可以保证必胜。
那么总点数是偶数怎么办呢?好说,我们直接从第二个点出发就行了,真的行么?这个时候却会出现一个问题,就是往前走,可能有某个点可以回到1,这样先手就输了,所以想得这么简单是不行的。
这道题限定了边不“交叉”,所以链一定可以被划分成若干个(可以只有1个)独立的区间,而我们从每个区间的开头出发,就不可能再回到之前的节点。
而我们如果从一段区间的中间出发,那么我们至多沿着某边回溯一次,然后就需要一直往前走,而开始节点的前一个节点,则是一个必胜节点。
这个时候我们进行讨论:(节点总数为偶,不然直接出解)
---------------------------------------------------
一、从奇点出发,先手可以选择在偶点回溯,如果此偶点可以回到偶点,即胜。而我们还需要保证在奇点对方无法回到偶点。
二、从偶点出发,先手可以选择在奇点回溯,如果此奇点可以回到奇点,即胜。而我们还需要保证在偶点对方无法回到奇点。
--------------------------------------------------
注意到上面两种情况,从奇点出发则必须回溯,而偶点则不然。所以我们可以特判一个区间的结束节点:
如果结束节点是偶,且不能回到奇点,那么必胜。
如果结束节点是奇,那我们不可以在结束节点开始,否则对方只需要往前一步,我们就输了,且无法逆转。
特判了结束节点以后,我们可以发现,如果我们可以在某个节点回溯,并且取得胜利,那么从开始节点到这个节点这一段区间,对方是不可以有逆转的机会的(奇点回偶/偶点回奇),这样我们不妨把开始节点无限右推,推到回溯节点前一位。
然后对于每段区间,我们只需要枚举回溯节点,然后check一下它的上一个节点是否可以逆转,就可以出解了。
显然这样扫一遍,发现所有的节点都是必败,那么这场博弈就输了,这样就只能输出“污得不行”了。
细节:我们记录了每个点能否回溯到奇/偶点,但是有可能能回溯,check却已经被堵?不可能。
因为奇需要回到奇,而我们是从它前一个点(偶)开始的,而偶则亦然。
话说这道题可以记忆化深搜水过么?如果可以,那么思路应该是只需要判断某个节点如果是一段区间的开始节点,那么它就只能往前走,不能回头,故它是一个结束节点,然后就可以记忆化进行推演了。
但是这道题中,一个节点并不是有出边就可以走的,,而状态压缩,更是活在梦里,随意YY了一下,感觉并不能这么水过。
我又想了一下,发现记忆化搜索的话你不知道那些点能走,哪些点不能,比如偶环套偶环,外面的偶环你倒是可以直接根据奇偶性判断胜负,里面的环呢?233。不需要卡!因为它本身就没法搜!要记忆化,只能先枚举开始点,(这样貌似依然不可行),然后再搜,即使可行,也是n^2的,显然TLE 了。。。
}
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1001000
using namespace std;
int n,m,vv[N],cnt;
bool jd[N][2];
void build_chain()
{
int a,b,c;
scanf("%d%d%d",&n,&m,&c);
for(int i=1;i<n;i++)vv[i]=i;
while(m--)
{
scanf("%d%d",&a,&b);
if(a==b||a==c||b==c)continue;
a=(a+n-c)%n,b=(b+n-c)%n;
if(a<b)
{
vv[a]=max(vv[a],b);
jd[b][a&1]=1;
}
else
{
vv[b]=max(vv[b],a);
jd[a][b&1]=1;
}
}
n--;
}
int l[N],r[N];
bool build_district()
{
for(int i=1;i<=n;i++)
{
cnt++;
if(vv[i]==i)return 1;
l[cnt]=i;
r[cnt]=i=vv[i];
}
return 0;
}
bool check(int f)
{
if((r[f]&1)==0&&jd[r[f]][1]==0)return 1;
for(int i=l[f]+1;i<=r[f];i++)
{
if((i&1)&&jd[i][1])
if(jd[i-1][1]==false)return 1;
if((i%2==0)&&jd[i][0])
if(jd[i-1][0]==false)return 1;
}
return 0;
}
int main()
{
build_chain();
if(!n)
{
puts("galaxy");
return 0;
}
if((n&1)||build_district()==1)
{
puts("dawn");
return 0;
}
for(int i=1;i<=cnt;i++)
{
if(check(i))
{
puts("dawn");
return 0;
}
}
puts("galaxy");
return 0;
}