Gym102055H Game on the Tree

Link
如果先手到某个关键点的距离比后手近,那么先手必胜。
否则此时先后手都会往环上走,而且先手到任意一个关键点的距离都比后手远。
如果先手和后手走上环的位置是同一个,那么此时后手离环肯定比先手近,因此先手走不上环,后手必胜。
如果先手比后手先走上环,那么此时不管先手往哪个关键点走,后手一定可以比先手先到这个关键点,因此后手必胜。
如果后手先上环,那么此时它无法根据先手的行动来决定自己的行动。
如果后手可以先于先手走到先手上环的那个点,先手就上不了环了,那么后手必胜。
否则此时后手需要去堵住在先手上环点两侧的最近的关键点所在链与环的交点。
如果后手可以在先手上环之前找到一个点,这个点满足到上述两个点的距离都比先手上环点短,那么后手就可以到这个点之后先停止不动,等先手上环之后模仿先手行动,此时后手必胜。
否则先手必胜。

#include<cctype>
#include<cstdio>
#include<cstring>
const int N=200007;
char ibuf[1<<27|1],*iS=ibuf,str[2][10]={"Sheep","Panda"};int n,tot,tim,len,top,head[N],is[N],d1[N],d2[N],d3[N],fa[N],id[N],cir[N],stk[N];
struct edge{int v,next;}e[2*N];
int read(){int x=0;while(isspace(*iS))++iS;while(isdigit(*iS))(x*=10)+=*iS++&15;return x;}
void add(int u,int v){e[++tot]={v,head[u]},head[u]=tot,e[++tot]={u,head[v]},head[v]=tot;}
void bfs(int s,int*dis)
{
    static int q[N],hd,tl;
    if(!s) return memset(dis+1,0,4*n),void();
    memset(dis+1,0x3f,4*n),q[hd=tl=1]=s,dis[s]=0;
    for(int i,u,v;hd<=tl;) for(i=head[u=q[hd++]];i;i=e[i].next) if(dis[v=e[i].v]>dis[u]+1) dis[v]=dis[u]+1,q[++tl]=v;
}
int find(int u,int from)
{
    static int vis[N];stk[++top]=u,vis[u]=tim;
    for(int i=head[u],v;i;i=e[i].next)
    {
	if(i==from) continue;
	if(vis[v=e[i].v]==tim) {for(int x=0;top&&x^v;)x=stk[top--],cir[++len]=x;return 1;}
	if(find(v,i^1)) return 1;
    }
    return --top,0;
}
void dfs(int u)
{
    for(int i=head[u],v;i;i=e[i].next) if(!id[v=e[i].v]&&v^fa[u]) fa[v]=u,dfs(v),is[v]|=is[u];
}
int solve()
{
    memset(is+1,0,4*n),memset(head+1,0,4*n),memset(fa+1,0,4*n),memset(id+1,0,4*n),len=top=0,tot=1,++tim,n=read();
    int u,v,flg,l1=0,l2=0,p1,p2;
    for(int i=1;i<=n;++i) add(read(),read());
    for(int m=read();m;--m) is[read()]=1;
    bfs(u=read(),d1),bfs(v=read(),d2);
    for(int i=1;i<=n;++i) if(is[i]&&d1[i]<=d2[i]) return 1;
    find(1,0);
    for(int i=1;i<=len;++i) id[cir[i]]=i;
    for(int i=1;i<=len;++i) dfs(cir[i]);
    while(fa[u]) u=fa[u],++l1;
    while(fa[v]) v=fa[v],++l2;
    if(u==v||l1<=l2) return 0;
    for(p1=id[u];p1^id[v]&&!is[cir[p1]];p1=(p1-2+len)%len+1);
    for(p2=id[u];p2^id[v]&&!is[cir[p2]];p2=p2%len+1);
    bfs(p1=p1==id[v]? 0:cir[p1],d1),bfs(p2=p2==id[v]? 0:cir[p2],d2),bfs(v,d3),flg=d3[u]>=l1-l2&&(p1||p2);
    for(int i=1,x;i<=len;++i)
    {
	x=cir[i],flg&=!(d3[x]<=l1-l2&&(!d1[x]||d1[x]<d1[u])&&(!d2[x]||d2[x]<d2[u]));
	if(d3[p1]&&d3[p1]<=l1-l2) flg&=!(d1[x]<=l1-l2-d3[p1]&&(!d2[x]||d2[x]<d2[u]));
	if(d3[p2]&&d3[p2]<=l1-l2) flg&=!(d2[x]<=l1-l2-d3[p2]&&(!d1[x]||d1[x]<d1[u]));
    }
    return flg;
}
int main(){fread(ibuf,1,1<<27,stdin);for(int T=read(),i=1;i<=T;++i)printf("Case %d: %s\n",i,str[solve()]);}
posted @ 2020-04-30 14:19  Shiina_Mashiro  阅读(212)  评论(0编辑  收藏  举报