• hdu 5909 Tree Cutting —— 点分治


    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909

    点分治,每次的 rt 是必选的点;

    考虑必须选根的一个连通块,可以DP,决策就是在每个子树中决定选不选子树根,如果不选就跳过这个子树;

    于是可以转化成 dfs 序上的DP;

    每次重新标记一遍 dfs 序,但不改动 siz (也许可以改动但T了?),可能因为 siz 还和点分治的过程有关。

    代码如下:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int const xn=1025,inf=1025,mod=1e9+7;
    int n,m,v[xn],hd[xn],ct,to[xn<<1],nxt[xn<<1],siz[xn],dfn[xn],g[xn],tim;
    int ans[xn],f[xn][xn],rt,mx,nt[xn];
    bool vis[xn];
    int rd()
    {
      int ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    void upt(int &x,int y){x+=y; while(x>=mod)x-=mod; while(x<0)x+=mod;}
    void add(int x,int y){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct;}
    void getrt(int x,int fa,int sum)
    {
      int nmx=0; siz[x]=1;
      for(int i=hd[x],u;i;i=nxt[i])
        {
          if((u=to[i])==fa||vis[u])continue;
          getrt(u,x,sum); siz[x]+=siz[u];
          if(siz[u]>nmx)nmx=siz[u];
        }
      nmx=max(nmx,sum-siz[x]);
      if(nmx<mx)mx=nmx,rt=x;
    }
    void dfs(int x,int fa)
    {
      dfn[x]=++tim; g[tim]=v[x];
      for(int i=hd[x],u;i;i=nxt[i])
        if((u=to[i])!=fa&&!vis[u])dfs(u,x);
      nt[dfn[x]]=tim+1;
    }
    void work(int x,int ss)
    {
      vis[x]=1; tim=0; dfs(x,0);
      for(int i=1;i<=ss+1;i++)memset(f[i],0,sizeof f[i]);
      f[2][g[1]]=1;
      for(int i=2;i<=ss;i++)
        for(int j=0;j<m;j++)
          if(f[i][j])upt(f[i+1][j^g[i]],f[i][j]),upt(f[nt[i]][j],f[i][j]);
      //printf("x=%d ss=%d
    ",x,ss);
      for(int j=0;j<m;j++)upt(ans[j],f[ss+1][j]);
      //,printf("f[%d][%d]=%d
    ",dfn[x]+siz[x],j,f[dfn[x]+siz[x]][j]);
      for(int i=hd[x],u;i;i=nxt[i])
        if(!vis[u=to[i]])
          {
        int ns=(siz[u]>siz[x]?ss-siz[x]:siz[u]);
        mx=inf; getrt(u,0,ns); work(rt,ns);
          }
    }
    int main()
    {
      int T=rd();
      while(T--)
        {
          n=rd(); m=rd(); 
          for(int i=1;i<=n;i++)v[i]=rd();
          ct=0; tim=0;
          for(int i=1;i<=n;i++)hd[i]=0;
          for(int i=1,x,y;i<n;i++)x=rd(),y=rd(),add(x,y),add(y,x);
          for(int j=0;j<m;j++)ans[j]=0;
          for(int i=1;i<=n;i++)vis[i]=0;
          mx=inf; getrt(1,0,n); work(rt,n);
          for(int j=0;j<m;j++)printf("%d%c",ans[j],j==m-1?'
    ':' ');
        }
      return 0;
    }
  • 相关阅读:
    使用 MVVMLight 命令绑定
    使用 MVVMLight 绑定数据
    在VS中安装/使用 MVVMLight
    关于 MVVMLight 设计模式系列
    DoBox 下载
    Visual Studio使用技巧,创建自己的代码片段
    List 和 ObservableCollection的区别
    HTTP 错误 404.3 解决
    WPF 跟踪命令和撤销命令(复原)
    WPF 自定义命令 以及 命令的启用与禁用
  • 原文地址:https://www.cnblogs.com/Zinn/p/10183035.html
Copyright © 2020-2023  润新知