HDU 5293 Tree chain problem

Tree chain problem

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 565    Accepted Submission(s): 137

Problem Description

Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.

There are m chain on the tree, Each chain has a certain weight. Coco would like to pick out some chains any two of which do not share common vertices.

Find out the maximum sum of the weight Coco can pick

Input

The input consists of several test cases. The first line of input gives the number of test cases T (T<=10).

For each tests:

First line two positive integers n, m.(1<=n,m<=100000)

The following (n - 1) lines contain 2 integers ai bi denoting an edge between vertices ai and bi (1≤ai,bi≤n),

Next m lines each three numbers u, v and val(1≤u,v≤n,0<val<1000), represent the two end points and the weight of a tree chain.

Output

For each tests:

A single integer, the maximum number of paths.

Sample Input

1
7 3
1 2
1 3
2 4
2 5
3 6
3 7
2 3 4
4 5 3
6 7 3

Sample Output

6

Hint

 Stack expansion program: #pragma comment(linker, "/STACK:1024000000,1024000000") 

Author

FZUACM

Source

2015 Multi-University Training Contest 1

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define prt(k) cerr<<#k" = "<<k<<endl
typedef unsigned long long ll;

const int N = 233333;
int n, m, head[N], mm;
struct Edge
{
    int v, next, w;
} e[N << 1];
void add(int u, int v, int w = 1)
{
    e[mm].v = v;
    e[mm].next = head[u];
    e[mm].w = w;
    head[u] = mm++;
}
int sz[N], dep[N];
int f[N][22]; /// f[i][j] 表示 i 的第 2^j 个祖先
int dfn[N];  ///dfs index
int cur;
int id[N]; /// you dfs xu qiu chu bian hao
int len[N];
int fa[N], son[N], top[N], p[N], pos;
/// fa 父节点   dep -- 深度     sz 孩子数    son 重儿子
/// top[u] 它所在重链顶端节点 p[u]在数据结构中位置 rp p的反
void dfs(int u, int pre = 1) /// 点从 1 开始标号
{
    sz[u] = 1;
    dfn[u] = ++cur;
    id[cur] = u;
    for (int i=head[u]; ~i; i=e[i].next)
    {
        int v = e[i].v;
        int w = e[i].w;
        if (v != pre)
        {
            dep[v] = dep[u] + 1;
            len[v] = len[u] + w;
            fa[v] = f[v][0] = u;
            dfs(v, u);
            sz[u] += sz[v];
            if (son[u]==-1 || sz[son[u]] < sz[v])
                son[u] = v;
        }
    }
}
/// top[u] 它所在重链顶端节点 p[u]在数据结构中位置
void getpos(int u, int v = 1)
{
    top[u] = v;
    p[u] = ++pos;
    if (~son[u]) getpos(son[u], v);
    for (int i=head[u]; ~i; i=e[i].next)
    {
        int v= e[i].v;
        if (v-son[u] && v-fa[u])
            getpos(v, v);
    }
}
int maxh;
void gao()
{
    cur = 0;
    dep[0] = -1;
    len[1] = dep[1] = 0;
    memset(son, -1, sizeof son);
    dfs(1, 0);
    int j;
    for (j=1; (1<<j)<n; j++)
        for (int i=1; i<=n; i++)
            f[i][j] = f[f[i][j-1]][j-1];
    maxh = j - 1;
    getpos(1);
}
int swim(int x, int k)
{
    for (int i=0; i<=maxh; i++)
        if (k >> i & 1)
            x = f[x][i];
    return x;
}
int LCA(int x, int y)
{
    if (dep[x] > dep[y]) swap(x, y); ///dep[x] <= dep[y];
    y = swim(y, dep[y] - dep[x]);
    if (x == y) return y;
    for (int i=maxh; i>=0; i--)
    {
        if (f[x][i] != f[y][i])
            x = f[x][i], y = f[y][i];
    }
    return f[x][0];
}
int lca[N];
struct P
{
    int u, v, w;
    P() {}
    P(int _u,int _v, int _w) {u=_u, v=_v, w=_w;}
} chain[N];  /// chains;
/******Bit Index Tree************/
struct Tree
{
    int tree[N<<2];
    void init()
    {
        memset(tree, 0, sizeof tree);
    }
    inline int low(int x)
    {
        return x & -x;
    }
    void Add(int i, int x)
    {
        for(; i<=n; i+=low(i)) tree[i]+=x;
    }
    int sum(int p)
    {
        int res = 0;
        for(int i=p; i>0; i-=low(i)) res+=tree[i];
        return res;
    }
    int query(int l, int r)
    {
        if (l > r) swap(l, r);
        return sum(r) - sum(l-1);
    }
} Td, Tsum;

/**********End Tree**********/
inline int get_sum(int u, int v)
{
    int f1 = top[u], f2 = top[v];
    int tmp = 0;
    int sum, d;
    while(f1 - f2)
    {
        if(dep[f1] < dep[f2])
        {
            swap(f1 ,f2);
            swap(u, v);
        }
        sum += Tsum.query(p[f1], p[u]);
        d += Td.query(p[f1], p[u]);
        u = fa[f1];
        f1 = top[u];
    }
    sum += Tsum.query(p[u], p[v]);
    d += Td.query(p[u], p[v]);
    return sum - d;
}
vector<int> vi[N]; /// vi[i] 存储以 i 为端点LCA的链编号
int d[N], sum[N];
void init()
{
    pos =0 ;
    mm = 0;
    memset(head,-1,sizeof head);
    memset(son, -1, sizeof son);
    for (int i=0;i<N;i++) vi[i].clear();
    Tsum.init();
    Td.init();
    memset(d ,0 , sizeof d);
}
void DP(int u, int fa = 1)
{
    sum[u] = 0;
    for (int i=head[u];~i;i=e[i].next)
    {
        int v = e[i].v;
        if (v==fa) continue;
        DP(v, u);
        sum[u] += d[v];
    }
    d[u] = sum[u];
    Tsum.Add(p[u], sum[u]);
    for (int p : vi[u]) {
        int a = chain[p].u;
        int b = chain[p].v;
        int w = chain[p].w;
        d[u] = max(d[u], w + get_sum(a, b));
    }
    Td.Add(p[u], d[u]);
}
int main()
{
    int re;
    scanf("%d", &re);
    while (re--)
    {
        scanf("%d%d", &n, &m);
        init();
        for (int i=0; i<n-1; i++)
        {
            int u, v;
            scanf("%d%d", &u, &v);
            add(u, v);
            add(v, u);
        }
        gao();
        for (int i=0; i<m; i++)
        {
            int u, v , w;
            scanf("%d%d%d", &u, &v, &w);
            lca[i] = LCA(u,v);
            vi[lca[i]].push_back(i);
            chain[i] = P(u, v, w);
        }
        DP(1, 1);
        printf("%d\n", d[1]);
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-07 04:16:02

HDU 5293 Tree chain problem的相关文章

hdu 5293 Tree chain problem(树链剖分+树形dp)

题目链接:hdu 5293 Tree chain problem 维护dp[u], sum[u],dp[u]表示以u为根节点的子树的最优值.sum[u]表示以u节点的所有子节点的dp[v]之和.对于边a,b,w,在LCA(a,b)节点的时候进行考虑.dp[u] = min{dp[u], Sum(a,b) - Dp(a,b) + sum[u] | (ab链上的点,不包括u } #pragma comment(linker, "/STACK:1024000000,1024000000")

HDU 5293 TREE CHAIN PROBLEM LCT+树形DP

题解链接 代码链接 链接 Tree chain problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 35    Accepted Submission(s): 8 Problem Description Coco has a tree, whose vertices are conveniently labeled by 1

(中等) HDU 5293 Tree chain problem,树链剖分+树形DP。

Problem Description Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.There are m chain on the tree, Each chain has a certain weight. Coco would like to pick out some chains any two of which do not share common vertices.Find out the

HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形dp, 对于每条链u,v,w,我们只在lca(u,v)的顶点上处理它 让dp[i]表示以i为根的指数的最大值,sum[i]表示dp[vi]的和(vi为i的儿子们) 则i点有两种决策,一种是不选以i为lca的链,则dp[i]=sum[i]. 另一种是选一条以i为lca的链,那么有转移方程:dp[i]=

HDU 5293(Tree chain problem-树链剖分)

Tree chain problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 940    Accepted Submission(s): 248 Problem Description Coco has a tree, whose vertices are conveniently labeled by 1,2,-,n. Th

HDOJ 5293 Tree chain problem LCA+树链剖分+树形DP

[题意] 给定一颗树上的几条链和每条链的权值,求能取出的不含有公共节点的链的最大权值.... [解] 预处理每条链的lca 树形DP, d[i]表示取到这个节点时可以得到的最大值 , sum[i]=sigma( d[k] | k 是i的子节点) 如果不取i  d[i]=sum[i] 如果取i , e是lca为i的链则 d[i]=max(d[i],e的权值+sigma(sum[k])-sigma(d[k]))  k为树链上的点 可以用树链剖分+树装数组在nlogn的时间复杂度内求链上的值 Tree

hdu5293(2015多校1)--Tree chain problem(树状dp)

Tree chain problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 262    Accepted Submission(s): 59 Problem Description Coco has a tree, whose vertices are conveniently labeled by 1,2,-,n. The

[2015hdu多校联赛补题]hdu5293 Tree chain problem

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意:给你一棵n个点的树,和一些该树上的树链,每个树链有一定的权值,要求选出一些不相交的树链,使他们的权值和尽量大 解: 树形dp,dp[x]表示以x为根节点的子树的解,那么就可以基于在当前结点对树链的选和不选进行dp 现在有两个问题: 1.在树链上的哪个点进行选择? 2.选和不选分别如何操作? 对于第一个问题,粗略想一下(在解决问题二的时候会发现),树链上最浅的一个点(也就是树链两端的lca

hdu5293 Tree chain problem 树形dp+线段树

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5293 在一棵树中,给出若干条链和链的权值.求选取不相交的链使得权值和最大. 比赛的时候以为是树链剖分就果断没去想,事实上是没思路. 看了题解,原来是树形dp.话说多校第一场树形dp还真多. . .. 维护d[i],表示以i为根节点的子树的最优答案. sum[i]表示i的儿子节点(仅仅能是儿子节点)的d值和. 那么答案就是d[root]. 怎样更新d值 d[i] = max(sum[i] , w[p]+s