您的位置:首页 > 大数据 > 人工智能

HDU 5293 Tree chain problem(树形DP+树链剖分)

2016-07-06 09:55 330 查看
题意:一颗n节点树上有m条链,每条链有权重,求一个链的集合使权重和最大且两两不相交。

解析:令dp[i]为以i为根的子树的最大权重和。

如果i不在链上,则有dp[i] = sigma(dp[k]) k为i的子节点

如果i在某一条链(u,v,w)上,那么dp[i] = w + sigma(dp[k]) k为链上所有节点的子节点。对于该值,我们可以统计统计链上节点的所有子节点dp的和 - 链上节点dp和(经树链剖分后用树状数组维护)。

[code]:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>

#define lson l , mid , rt<<1
#define rson mid+1, r, rt<<1|1
#define lowbit(i) (i&-i)
using namespace std;
const int maxn = 1e5+5;

inline bool read(int &ret){
char c;int sgn;
if(c = getchar(),c==EOF) return 0;
while(c != '-'&&(c<'0'||c>'9')) c=getchar();
sgn = (c=='-')?-1:1;
ret = (c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
ret*=sgn;
return 1;
}

struct Chain{
int u,v,w;
Chain(int u,int v,int w):u(u),v(v),w(w){}
};
struct Nod{
int b,next;
void init(int b,int next){
this->b=b;this->next=next;
}
}buf[2*maxn];
int n,m,len,E[maxn];
vector<Chain> G[maxn];

struct LCA{
int rmq[maxn<<1],pos[maxn<<3];
int F[maxn<<1],P[maxn],lca;

void dfs(int u,int pre,int deep){
int i,v;
lca++;F[lca]=u;P[u]=lca;rmq[lca]=deep;
for(i=E[u];i!=-1;i=buf[i].next){
v = buf[i].b;
if(v == pre) continue;
dfs(v,u,deep+1);
lca++;F[lca]=u;rmq[lca]=deep;
}
}
void build(int l,int r,int rt){
if(l == r) { pos[rt] = l; return; }
int mid = (l + r) >> 1;
build(lson);build(rson);
pos[rt] = rmq[pos[rt<<1]] < rmq[pos[rt<<1|1]]? pos[rt<<1]:pos[rt<<1|1];
}
int query(int a,int b,int l,int r,int rt){
if(l > b || r < a) return 0;
if(a <= l && r <= b) return pos[rt];
int o1,o2,mid = (l + r) >>1;
o1 = query(a,b,lson);o2 = query(a,b,rson);
return rmq[o1] < rmq[o2] ? o1 : o2;
}
void make(int root){
lca = 0;
memset(rmq,63,sizeof(rmq));
dfs(root,-1,0);
build(1,lca,1);
}
int ancestor(int a,int b){
int ca = P[a],cb = P[b];
if(ca > cb) swap(ca,cb);
return F[query(ca,cb,1,lca,1)];
}
}ac;

int dp[maxn];
int num[maxn],dep[maxn],par[maxn],son[maxn],head[maxn],P[maxn],cnt;

struct BIT{
int bit[2][maxn],range;
void init(int range){
this->range = range;
for(int i = 1;i <= range;i++) bit[0][i] = bit[1][i] = 0;
}
void add(int k,int x,int id){
for(;k<=range;k+=lowbit(k)) bit[id][k]+=x;
}
int sum(int k,int id){
int res = 0;
for(;k;k-=lowbit(k)) res += bit[id][k];
return res;
}
int query(int l,int r,int id){
return sum(r,id)-sum(l-1,id);
}
}bt;

void init(){
len = cnt = 0;
memset(E,-1,n*sizeof(int));
for(int i = 0;i < n;i++) G[i].clear();
}
void add_edge(int a,int b){
buf[len].init(b,E[a]);E[a]=len++;
buf[len].init(a,E[b]);E[b]=len++;
}
void dfs(int u,int pre){
int i,v;
num[u] = 1;son[u] = -1;par[u] = pre;dep[u] = pre!=-1?dep[pre]+1:0;
for(i=E[u];i!=-1;i=buf[i].next){
v = buf[i].b;
if(v == pre) continue;
dfs(v,u);
if(son[u]==-1||num[v]>num[son[u]]) son[u] = v;
num[u]+=num[v];
}
}
void buildQTree(int u,int hd){
int i,v;
cnt++;
head[u] = hd;P[u]=cnt;
if(son[u]!=-1) buildQTree(son[u],hd);
for(i=E[u];i!=-1;i=buf[i].next){
v = buf[i].b;
if(v == son[u] || v == par[u]) continue;
buildQTree(v,v);
}
}
int query(int a,int b,int id){
int ha = head[a],hb = head[b], res = 0;
while(ha != hb){
if(ha == -1 || (ha != -1 && hb != -1 && dep[ha] < dep[hb])){
swap(ha,hb);swap(a,b);
}
res += bt.query(P[ha],P[a],id);
a = par[ha];ha = a != -1 ?head[a] :-1;
}
if(a == b) return res + bt.query(P[a],P[a],id);
if(dep[a] > dep[b]) swap(a,b);
return res + bt.query(P[a],P[b],id);
}
void DP(int u,int pre){
int i,v,v1,v2,w,sum = 0;
dp[u] = 0;
for(i = E[u];i != -1;i = buf[i].next){
v = buf[i].b;
if(v == pre) continue;
DP(v,u);
dp[u] += dp[v];
//bt.add(P[u],dp[v],1);
}
bt.add(P[u],dp[u],1);
sum = dp[u];
//printf("current node %d\n",u);
for(i = 0;i < G[u].size();i++){
v1 = G[u][i].u;v2 = G[u][i].v;w = G[u][i].w;
// dp[u] = max(dp[u],w-sum+query(v1,u,1)-query(v1,u,0)
// +query(v2,u,1)-query(v2,u,0));
//printf("%d %d %d %d\n",query(v1,u,1),query(v1,u,0)
// ,query(v2,u,1),query(v2,u,0));
dp[u] = max(dp[u],w+query(v1,v2,1)-query(v1,v2,0));
//printf("temp : %d %d %d\n",query(v1,v2,1),query(v1,v2,0),w+query(v1,v2,1)-query(v1,v2,0));
//printf("-> %d %d %d %d\n",v1,v2,w,dp[u]);
}
//printf("answer %d\n",dp[u]);
bt.add(P[u],dp[u],0);
}

int main(){
int i,j,cas,u,v,w,op;
read(cas);
while(cas--){
read(n);read(m);
init();
for(i = 1;i < n;i++){
read(u);read(v);u--,v--;
add_edge(u,v);
}
ac.make(0);
for(i = 0;i < m;i++){
read(u);read(v);read(w);u--,v--;
G[ac.ancestor(u,v)].push_back(Chain(u,v,w));
}
dfs(0,-1);
buildQTree(0,0);
bt.init(cnt);
DP(0,-1);
printf("%d\n",dp[0]);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: