zoukankan      html  css  js  c++  java
  • AGC010F Tree Game

    题意简述:给定一颗有(N(N<=3000))个节点的树,每个点有一定权值,双方轮流执行:将当前位置权值-1,并将之移动至相邻节点,先无法移动者输;问初始在哪些节点可使先手必胜。

    比较有意思的博弈题。

    对于任意结点(r),我们考虑以它为根。然后我们定义函数(f(x)=0/1)表示在以x为根的子树内,是否能够做到先手必胜。那么(f(x)=1)的必要条件就是对于(x)的子结点,存在一个(v)(f(v)=0)(val_v<val_x)。因为在以v为根的子树内,无论怎么走都无法使先手获胜,那么以(x)为起点的话,先手直接走到(v)就可以了,后手就变成了先手。还要避免先后手秦王绕柱走的情况,所以(val_v<val_x)。所以若(r)作为起始点可行,那么(f(r)=1)

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=3010;
    struct fk{int to,nxt;}e[N<<1];
    int f[N],n,cnt,head[N],val[N];
    void add(int u,int v){e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;}
    void dfs(int u,int fa){
        f[u]=0;
        for(int i=head[u],v;i;i=e[i].nxt)
            if((v=e[i].to)!=fa){
                dfs(v,u);
                if(!f[v]&&val[u]>val[v])f[u]=1;
            }
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&val[i]);
        for(int u,v,i=1;i<n;i++)
            scanf("%d%d",&u,&v),add(u,v),add(v,u);
        for(int i=1;i<=n;i++){
            dfs(i,0);
            if(f[i])printf("%d ",i);
        }
        puts("");
    }
    
  • 相关阅读:
    捕捉整个桌面的图片
    在Image控件中绘制文字
    绘图
    Image1.Canvas画图笔刷
    将图片序列保存为GIF文件
    拷贝剪贴板图像到窗体
    显示 png 图片
    将图片以字符串方式保存
    复制图片的一部分
    反转字符串
  • 原文地址:https://www.cnblogs.com/yxc2003/p/10751450.html
Copyright © 2011-2022 走看看