zoukankan      html  css  js  c++  java
  • 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
    ",i,str[solve()]);}
    
  • 相关阅读:
    PHP面向对象——三大基本特性与五大基本原则
    PHP面向对象——GD库实现图片水印和缩略图
    php系统函数-----数组函数
    PHP面向对象(OOP)----分页类
    郑军学长-解决SVN访问慢[密]
    如何减少换页错误?
    什么是正则表达式?
    MFC通过ADO操作Access数据库(详细)
    xml 转义特殊字符 如&'"
    MFC操作串口,详细
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12808638.html
Copyright © 2011-2022 走看看