zoukankan      html  css  js  c++  java
  • 【计蒜客习题】蒜头君的建设方案


    说是树状DP的入门水题,然而甚至感觉不到DP的存在。。。

    好吧,理论上这个确实是DP,由之前阶段推出当前阶段,以子结点为根的子树结点个数可以推出以父结点为根的子树结点个数。

    然后针对每条边,根据题目要求的那样统计答案即可。不过我们统计时利用的应该是子结点的信息,怎么找到子结点?因为父结点的信息是由子结点的信息得来的,所以一定大于子结点。

    另外,因为树状DP是建立在树这一数据结构上的,因此可以用到与树相关的各种特殊性质。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 inline int abs(int i) {if(i<0) i=-i;return i;}
     6 const int maxn=1e6+5;
     7 int n,head[maxn],eid,vis[maxn],size[maxn];
     8 long long ans;
     9 struct edge {
    10     int u,v,w,next;
    11     edge(int u=0,int v=0,int w=-1):u(u),v(v),w(w) {}
    12 } E[2*maxn];
    13 void insert(int u,int v,int w) {
    14     E[eid]=edge(u,v,w);
    15     E[eid].next=head[u];
    16     head[u]=eid++;
    17 }
    18 int dfs(int u) {
    19     size[u]=1;
    20     for(int p=head[u];p+1;p=E[p].next) {
    21         int v=E[p].v;
    22         if(vis[v]) continue;
    23         vis[v]=1;
    24         size[u]+=dfs(v);
    25     }
    26     return size[u];
    27 }
    28 int main() {
    29     scanf("%d",&n);
    30     memset(head,-1,sizeof(head));
    31     int s,t,c;
    32     for(int i=1;i<n;++i) {
    33         scanf("%d%d%d",&s,&t,&c);
    34         insert(s,t,c);
    35         insert(t,s,c);
    36     }
    37     vis[1]=1;
    38     dfs(1);
    39     for(int i=0;i<eid;i+=2) {
    40         int u=E[i].u,v=E[i].v,w=E[i].w;
    41         if(size[u]>size[v]) swap(u,v);
    42         ans+=w*1LL*abs(2*size[u]-n);
    43     }
    44     printf("%lld",ans);
    45     return 0;
    46 }
    AC代码
  • 相关阅读:
    c++ 为自定义类添加stl遍历器风格的遍历方式
    C++ 生成随机数
    c/c++ 函数说明以及技巧总结
    XSLT 教程
    C# 高效过滤DataTable 中重复数据方法
    xml获取指定节点的路径
    TreeView控件
    推荐一些C#相关的网站、资源和书籍
    C#多线程操作
    C#二进制序列化
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9644392.html
Copyright © 2011-2022 走看看