zoukankan      html  css  js  c++  java
  • HDOJ树形DP专题之Contestants Division

    题目链接

    题目大意:给定一棵树,每个结点有一个权值,一棵树的权值为所有结点的权值和,现将这棵树分为两棵子树,要使得两子树的权值差最小。

    我的做法是先将无根树化为有根树,然后求每棵子树的权值,最后用一次扫描求结果。需要注意的是结果要用long long型。

    View Code
     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <vector>
     4 #define N 100000
     5 #define MAX(a,b) ((a)>(b)?(a):(b))
     6 #define MIN(a,b) ((a)<(b)?(a):(b))
     7 #define D(a,b) ((a)>(b)?(a)-(b):(b)-(a))
     8 using namespace std;
     9 vector<int> g[N],dep[N];
    10 int n,m,a[N],d[N],p[N],dmax;
    11 long long sum[N],ans;
    12 void make_set()
    13 {
    14   for(int i=0;i<n;i++)  p[i]=i;
    15 }
    16 int find_set(int i)
    17 {
    18   return i==p[i]?p[i]:(p[i]=find_set(p[i]));
    19 }
    20 void dfs(int u,int fa)
    21 {
    22   int i,v,l;
    23   d[u]=(fa==-1?0:d[fa]+1);
    24   dmax=MAX(dmax,d[u]);
    25   dep[d[u]].push_back(u);
    26   l=g[u].size();
    27   for(i=0;i<l;i++)
    28   {
    29     v=g[u][i];
    30     if(v!=fa) dfs(v,p[v]=u);
    31   }
    32 }
    33 void dp()
    34 {
    35   int i,j,l,v;
    36   memset(sum,0,sizeof(sum));
    37   for(i=dmax;i>=0;i--)
    38   {
    39     l=dep[i].size();
    40     for(j=0;j<l;j++)
    41     {
    42       v=dep[i][j];
    43       sum[v]+=a[v];
    44       if(i>0) sum[p[v]]+=sum[v];
    45     }
    46   }
    47 }
    48 int main()
    49 {
    50   int i,u,v,kase=0;
    51   while(scanf("%d%d",&n,&m)&&n)
    52   {
    53     for(i=0;i<n;i++)  scanf("%d",&a[i]);
    54     for(i=0;i<n;i++)  g[i].clear();
    55     make_set();
    56     for(i=0;i<m;i++)
    57     {
    58       scanf("%d%d",&u,&v);
    59       u--,v--;
    60       if(find_set(u)==find_set(v))  continue;
    61       p[v]=u;
    62       g[u].push_back(v);
    63       g[v].push_back(u);
    64     }
    65     for(i=0;i<n;i++)  dep[i].clear();
    66     dmax=0;
    67     dfs(0,-1);
    68     dp();
    69     ans=sum[0];
    70     for(i=1;i<n;i++)  ans=MIN(ans,D(sum[i],sum[0]-sum[i]));
    71     printf("Case %d: %lld\n",++kase,ans);
    72   }
    73   return 0;
    74 }
  • 相关阅读:
    初学vue,vue2.0+vue-router+vuex的小项目
    解决安卓键盘将下面元素顶上来的问题
    ng1 与 vue 状态管理比较--个人理解
    js数组内元素移动,适用于拖动排序
    vuex--mutation,action个人理解
    git--删除.DS_Store
    app的设计 有感
    transformClassesWithDexForArmv7Debug --解决办法
    :mergeArmv7DebugResources:Some file crunching failed, see logs for details解决办法
    CET-6 分频周计划生词筛选(Week 2)
  • 原文地址:https://www.cnblogs.com/algorithms/p/2474293.html
Copyright © 2011-2022 走看看