zoukankan      html  css  js  c++  java
  • BZOJ3425 : Poi2013 Polarization

    最小值肯定是把树看作二分图,此时答案为$n-1$。

    最大值一定是选取重心为根,任意一个子树要么全部指向根,要么全部背离根,这样可以制造最大的星型图。

    统计出每个子树的大小后做01背包,如果小于$sqrt{n}$,那么二进制拆分,否则这种子树不超过$sqrt{n}$个,直接DP即可。

    用bitset优化转移,时间复杂度$O(frac{nsqrt{n}}{32})$。

    #include<cstdio>
    #include<bitset>
    #include<algorithm>
    #define N 250010
    using namespace std;
    int n,m,i,j,k,x,y,g[N],v[N<<1],nxt[N<<1],ed,son[N],f[N],S,cnt[N],q[N],t;
    bitset<N>dp;long long ans,sum;
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
    void findroot(int x,int y){
      son[x]=1;
      for(int i=g[x];i;i=nxt[i])if(v[i]!=y){
        findroot(v[i],x);
        son[x]+=son[v[i]];
        if(son[v[i]]>f[x])f[x]=son[v[i]];
      }
      if(n-son[x]>f[x])f[x]=n-son[x];
      if(f[x]<f[S]||!S)S=x;
    }
    void dfs(int x,int y){
      son[x]=1;
      for(int i=g[x];i;i=nxt[i])if(v[i]!=y)dfs(v[i],x),son[x]+=son[v[i]];
      if(y==S)if(son[x]<=m)cnt[son[x]]++;else q[++t]=son[x];
      sum+=son[x]-1;
    }
    int main(){
      read(n);
      for(i=1;i<n;i++)read(x),read(y),add(x,y),add(y,x);
      findroot(1,0);
      while(m*m<n)m++;
      dfs(S,0);
      dp[0]=1;
      while(t)dp|=dp<<q[t--];
      for(i=1;i<=m;i++)for(j=cnt[i],k=1;j;j-=k,k<<=1){
        if(j<=k){dp|=dp<<i*j;break;}
        dp|=dp<<i*k;
      }
      for(i=0;i<n;i++)if(dp[i])ans=max(ans,1LL*i*(n-i-1));
      return printf("%d %lld",n-1,ans+sum),0;
    }
    

      

  • 相关阅读:
    微信开发-微信支付(v3.3以上版本)
    微信开发-微信一般帮助类
    公司级平台_IProgram_Model
    公司级平台-IProgram_BLL
    公司级平台-IProgram-DAL
    公司级平台-IProgram-IBaseProgram
    公司级平台 -接口层IProgram
    asp mvc 中重写JsonResult,解决Json返回值序列化问题
    GPIO位带操作点亮LED,且使用按键控制开关
    按键检测GPIO输入
  • 原文地址:https://www.cnblogs.com/clrs97/p/5289359.html
Copyright © 2011-2022 走看看