zoukankan      html  css  js  c++  java
  • [2015hdu多校联赛补题]hdu5293 Tree chain problem

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5293

    题意:给你一棵n个点的树,和一些该树上的树链,每个树链有一定的权值,要求选出一些不相交的树链,使他们的权值和尽量大

    解:

    树形dp,dp[x]表示以x为根节点的子树的解,那么就可以基于在当前结点对树链的选和不选进行dp

    现在有两个问题:

    1、在树链上的哪个点进行选择?

    2、选和不选分别如何操作?

    对于第一个问题,粗略想一下(在解决问题二的时候会发现),树链上最浅的一个点(也就是树链两端的lca)上选择是可行的

    对于第二个问题,(假设现在在点u)不选的话,dp[u]=Sum(dp[v])(v为u的子节点),用sum[u]记录Sum(dp[v])(v为u的子节点),有dp[u]=sum[u]

    选择的话,对于每一个lca在u点的树链c,

    dp[u]=max(dp[u],Sum(dp[v1])+c.w(v1为c上所有节点的子节点, c.w为该链的权值))

    dp[u]=max(dp[u],Sum(sum[x])-Sum(dp[x])+c.w(x为c上所有节点, c.w为该链的权值))

    这个链上所有节点的某值和,用dfs序+树状数组维护一下就好了

      1 /*
      2  * Problem:  
      3  * Author:  SHJWUDP
      4  * Created Time:  2015/8/2 星期日 22:07:32
      5  * File Name: 233.cpp
      6  * State: 
      7  * Memo: 
      8  */
      9 #include <iostream>
     10 #include <cstdio>
     11 #include <cstring>
     12 #include <algorithm>
     13 #include <vector>
     14 #pragma comment(linker, "/STACK:1024000000,1024000000") 
     15 
     16 using namespace std;
     17 
     18 struct Edge {
     19     int u, v;
     20     Edge(int u, int v):u(u), v(v){}
     21 };
     22 struct Chain {
     23     int a, b, w;
     24     int lca;
     25 };
     26 struct Fenwick {
     27     int n;
     28     vector<int> c;
     29     void init(int n) {
     30         this->n=n;
     31         c.assign(n+1, 0);
     32     }
     33     int lowbit(int x) {
     34         return x & -x;
     35     }
     36     void add(int x, int v) {
     37         while(x<=n) {
     38             c[x]+=v; x+=lowbit(x);
     39         }
     40     }
     41     int getsum(int x) {
     42         int res=0;
     43         while(x>0) {
     44             res+=c[x]; x-=lowbit(x);
     45         }
     46         return res;
     47     }
     48 } fw1, fw2;
     49 
     50 int n, m;
     51 vector<Edge> edges;
     52 vector<vector<int> > G;
     53 vector<Chain> chain;
     54 vector<int> ln, rn, dep, dp, sum;
     55 vector<vector<int> > fa, arr;
     56 int root, cnt;
     57 void init(int sz) {
     58     edges.clear();
     59     G.assign(sz, vector<int>(0));
     60     chain.resize(sz);
     61     ln.resize(sz); rn.resize(sz); dep.resize(sz); dp.resize(sz); sum.resize(sz);
     62     fa.assign(sz, vector<int>(20));
     63     arr.assign(sz, vector<int>(0));
     64     fw1.init(sz<<1); fw2.init(sz<<1);
     65 }
     66 void addEdge(int u, int v) {
     67     edges.push_back(Edge(u, v));
     68     G[u].push_back(edges.size()-1);
     69 }
     70 void dfs1(int u) {
     71     ln[u]=++cnt;
     72     for(int k=1; k<20; k++) fa[u][k]=fa[fa[u][k-1]][k-1];
     73     for(int i : G[u]) {
     74         Edge & e=edges[i];
     75         if(e.v==fa[u][0]) continue;
     76         fa[e.v][0]=u;
     77         dep[e.v]=dep[u]+1;
     78         dfs1(e.v);
     79     }
     80     rn[u]=++cnt;
     81 }
     82 int lca(int u, int v) {
     83     if(dep[u]<dep[v]) swap(u, v);
     84     for(int k=19; k>=0; k--) {
     85         if(dep[fa[u][k]]>=dep[v]) {
     86             u=fa[u][k];
     87         }
     88     }
     89     if(u==v) return u;
     90     for(int k=19; k>=0; k--) {
     91         if(fa[u][k]!=fa[v][k]) {
     92             u=fa[u][k]; v=fa[v][k];
     93         }
     94     }
     95     return fa[u][0];
     96 }
     97 void dfs2(int u) {
     98     dp[u]=sum[u]=0;
     99     for(int i : G[u]) {
    100         Edge & e=edges[i];
    101         if(e.v==fa[u][0]) continue;
    102         dfs2(e.v);
    103         sum[u]+=dp[e.v];
    104     }
    105     dp[u]=sum[u];
    106     for(int i : arr[u]) {
    107         Chain & c=chain[i];
    108         int tmp=fw1.getsum(ln[c.a])+fw1.getsum(ln[c.b])
    109             -fw2.getsum(ln[c.a])-fw2.getsum(ln[c.b])+sum[u];
    110         dp[u]=max(dp[u], tmp+c.w);
    111     }
    112     fw1.add(ln[u], sum[u]); fw1.add(rn[u], -sum[u]);
    113     fw2.add(ln[u], dp[u]); fw2.add(rn[u], -dp[u]);
    114 }
    115 int main() {
    116 #ifndef ONLINE_JUDGE
    117     freopen("in", "r", stdin);
    118     //freopen("out", "w", stdout);
    119 #endif
    120     int T;
    121     scanf("%d", &T);
    122     while(T--) {
    123         scanf("%d%d", &n, &m);
    124         init(n+1);
    125         for(int i=1; i<n; i++) {
    126             int a, b;
    127             scanf("%d%d", &a, &b);
    128             addEdge(a, b);
    129             addEdge(b, a);
    130         }
    131         root=1; cnt=0; dep[root]=0; fa[root][0]=root; dfs1(root);
    132         for(int i=0; i<m; i++) {
    133             scanf("%d%d%d", &chain[i].a, &chain[i].b, &chain[i].w);
    134             chain[i].lca=lca(chain[i].a, chain[i].b);
    135             arr[chain[i].lca].push_back(i);
    136         }
    137         dfs2(root);
    138         printf("%d
    ", dp[root]);
    139     }
    140     return 0;
    141 }
    hdu 5293
  • 相关阅读:
    递归
    lecture-11
    最近公共祖先LCA
    微软面试100题
    0-1背包问题
    ubuntu网络已禁用解决办法
    cors(cross-resource-oragin-sharing 跨域资源共享) 解决跨域问题
    本地修改域名对应的IP地址
    oracle 解锁用户被锁住
    oracle 改变表中 某列的数据类型(该列已有数据)
  • 原文地址:https://www.cnblogs.com/shjwudp/p/4697045.html
Copyright © 2011-2022 走看看