• BZOJ2681 : 玩游戏2


    首先若存在多个连通块,那么答案显然是$+infty$。

    否则以$m$为根,每棵子树的根节点都最多只能放一个金币,且这些子树之间互不干扰。

    对于一棵父亲为$m$的子树,最优方案下一定可以将子树剖分成若干条祖先到孙子的链,每条链中每个点$x$往上贡献$lfloorfrac{v[x]}{2} floor$个金币,且不能贡献到其它链上去,因此一条有$k$个点的链最多可以放$2^k-1$个金币。

    设$f[i][j]$表示考虑$i$的子树,$i$所在链里有$j$个点时最多能放的金币数,枚举链的接法转移即可。

    时间复杂度$O(n^2)$。

    #include<cstdio>
    typedef long long ll;
    const int N=70;
    const ll inf=1LL<<50;
    int n,m,i,j,ed,g[N],v[N<<1],nxt[N<<1];char s[N];ll p[N],f[N][N],h[N],ans;
    inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
    inline void up(ll&a,ll b){
      if(b>inf)b=inf;
      if(a<b)a=b;
    }
    void dfs(int x,int y){
      int i,j,k,u;
      for(i=0;i<=n;i++)f[x][i]=-1;
      f[x][1]=0;
      for(i=g[x];i;i=nxt[i]){
        u=v[i];
        if(u==y)continue;
        dfs(u,x);
        for(j=0;j<=n;j++)h[j]=-1;
        ll tmp=0;
        for(j=1;j<=n;j++)if(~f[x][j]){
          up(h[j],f[x][j]+f[u][0]);
          up(tmp,f[x][j]+p[j-1]);
        }
        for(j=1;j<n;j++)if(~f[u][j])up(h[j+1],f[u][j]+tmp);
        for(j=0;j<=n;j++)f[x][j]=h[j];
      }
      for(i=1;i<=n;i++)if(~f[x][i])up(f[x][0],f[x][i]+p[i]);
    }
    int main(){
      for(p[0]=i=1;i<N;i++)up(p[i],p[i-1]*2);
      for(i=0;i<N;i++)p[i]--;
      while(~scanf("%d%d",&n,&m)){
        for(i=1;i<=n;i++)g[i]=0;
        for(ed=0,i=1;i<=n;i++){
          scanf("%s",s+1);
          for(j=1;j<=n;j++)if(s[j]=='Y')add(i,j);
        }
        if(ed/2!=n-1){
          puts("-1");
          continue;
        }
        ans=0;
        for(i=g[m];i;i=nxt[i]){
          dfs(v[i],m);
          up(ans,ans+f[v[i]][0]);
        }
        if(ans>2000000000)ans=-1;
        printf("%lld
    ",ans);
      }
      return 0;
    }
    

      

  • 相关阅读:
    启动Kafka
    利用Flume将本地文件数据中收集到HDFS
    集群安装hbase
    安装并配置hive
    python文件引用其他文件中的变量
    模拟用户登录爬取淘宝数据
    信息领域热词分析系统--详细设计说明书
    信息领域热词分析系统--词云
    《TCP/IP详解卷1:协议》——第4章 ARP:地址解析协议(转载)
    深入理解计算机系统——第12章:多线程中共享变量
  • 原文地址:https://www.cnblogs.com/clrs97/p/9515462.html
Copyright © 2020-2023  润新知