• 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()]);}
    
  • 相关阅读:
    百度地图定位经纬度返回4.9E-324有关问题
    急!JDBC问题,发生通信错误。错误位置:Reply.fill()。消息:数据不足。 ERRORCODE=-4499, SQLSTATE=08001
    Android 图片添加水印图片或者文字
    查询出多条记录,取最大或最小的某条件的记录,取唯一记录
    listView获取item的Edit内容,listView中的edit内容在滚动时自动赋值了前面的内容
    ListView中的item的按照和item点击事件并存
    update select
    db2 怎么计算两个时间相差多少个月。如2015-10-10 和2014-1-12
    解决AndroidADT自带Eclipse编辑器不能自动代码提示的问题
    python协程详解,gevent asyncio
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12808638.html
Copyright © 2020-2023  润新知