2013-11-17 08:52

原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=1040

N个骑士,每个人有一个仇人,那么,每个骑士只有一个后继,将他和他憎恨的人连边,就组成了

一颗内向树,内向树可以看成环儿上挂一堆树,那么我们对于每个环儿上的点,求出以该点为根节点

的子树,取不取该根节点的价值(树P就好了,类似于没有上司的舞会),然后我们得到了一个环儿

知道每个点取不取的价值,求最大价值,那么我们可以破环为链,固定第一个取不取,然后DP,如果

第一个取,那么答案就是c[tot,0],不取的话答案就是max(c[tot,1],c[tot,0]),tot为环最后一个节点

然后取两个的最大值就好了,因为可能图有多个块,所以累加每个块的最大值就是ans。

Ps:我知道我的代码写的长。。。。风格。。。

//By BLADEVIL
var
n :int64;
pre, last, other :array[..] of int64;
l :int64;
low, dfn, stack, key :array[..] of int64;
flag :array[..] of boolean;
time :int64;
que :array[..] of int64;
fuck :int64;
tot :int64;
v :array[..] of int64;
w, c :array[..,..] of int64;
finish :array[..] of boolean;
ans :int64; function min(a,b:int64):int64;
begin
if a>b then min:=b else min:=a;
end; function max(a,b:int64):int64;
begin
if a>b then max:=a else max:=b;
end; procedure connect(x,y:int64);
begin
inc(l);
pre[l]:=last[x];
last[x]:=l;
other[l]:=y;
end; procedure init;
var
i :longint;
y :int64;
begin
read(n);
for i:= to n do
begin
read(v[i],y);
connect(y,i);
end;
end; procedure dfs(x:int64);
var
p, q :int64;
cur :int64;
begin
inc(time);
dfn[x]:=time;
low[x]:=time;
inc(tot);
stack[tot]:=x;
flag[x]:=true; q:=last[x];
while q<> do
begin
p:=other[q];
if dfn[p]= then
begin
dfs(p);
low[x]:=min(low[x],low[p]);
end else
if flag[p] then low[x]:=min(low[x],dfn[p]);
q:=pre[q];
end; cur:=-;
if dfn[x]=low[x] then
begin
while cur<>x do
begin
cur:=stack[tot];
dec(tot);
flag[cur]:=false;
key[cur]:=x;
end;
end;
end; procedure doit(x:int64);
var
q, p :int64;
h, t :int64;
cur :int64;
i :longint;
now :int64; begin
t:=; h:=;
que[]:=x; q:=last[x];
while t<>h do
begin
inc(h);
cur:=que[h];
q:=last[cur];
while q<> do
begin
p:=other[q];
if key[p]=fuck then
begin
q:=pre[q];
continue;
end;
inc(t);
que[t]:=p;
q:=pre[q];
end;
end;
for i:=t downto do
begin
now:=que[i];
q:=last[now];
w[now,]:=v[now];
if q= then w[now,]:=v[now];
while q<> do
begin
p:=other[q];
if key[p]<>fuck then
begin
w[now,]:=w[now,]+max(w[p,],w[p,]);
w[now,]:=w[now,]+w[p,];
end;
q:=pre[q];
end;
end;
end; procedure main;
var
i, j :longint;
q, p :int64;
f :boolean;
now :int64; begin
for i:= to n do if dfn[i]= then dfs(i);
for i:= to n do if (low[i]<>dfn[i]) and (not finish[key[i]]) then
begin
fuck:=key[i]; finish[fuck]:=true;
for j:= to n do if key[j]=fuck then doit(j);
fillchar(flag,sizeof(flag),false);
for j:= to n do if key[j]=fuck then break;
fillchar(que,sizeof(que),);
que[]:=j; tot:=;
f:=false;
while true do
begin
q:=last[que[tot]];
while q<> do
begin
p:=other[q];
if flag[p] then
begin
f:=true;
break;
end;
if key[p]=fuck then
begin
inc(tot);
que[tot]:=p;
flag[p]:=true;
end;
q:=pre[q];
end;
if f then break;
end;
fillchar(c,sizeof(c),);
c[que[],]:=-maxlongint; c[que[],]:=w[que[],];
for j:= to tot- do
begin
c[que[j],]:=max(c[que[j-],],c[que[j-],])+w[que[j],];
c[que[j],]:=c[que[j-],]+w[que[j],];
end;
now:=-maxlongint;
for j:= to tot- do now:=max(now,max(c[que[j],],c[que[j],]));
fillchar(c,sizeof(c),);
c[que[],]:=w[que[],]; c[que[],]:=-maxlongint;
for j:= to tot- do
begin
c[que[j],]:=max(c[que[j-],],c[que[j-],])+w[que[j],];
c[que[j],]:=c[que[j-],]+w[que[j],];
end;
for j:= to tot- do now:=max(now,max(c[que[j],],c[que[j],]));
now:=max(now,c[que[tot-],]);
inc(ans,now);
end;
writeln(ans);
end; begin
init;
main;
end.

bzoj1040 内向树DP的更多相关文章

  1. bzoj1040 基环树森林dp

    https://www.lydsy.com/JudgeOnline/problem.php?id=1040 Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社 ...

  2. 初涉基环外向树dp&&bzoj1040: [ZJOI2008]骑士

    基环外向树dp竟然如此简单…… Description Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发 ...

  3. 【距离GDKOI:44天&GDOI:107天】【BZOJ1040】[ZJOI2008] 骑士 (环套树DP)

    其实已经准备退役了,但GDOI之前还是会继续学下去的!!当成兴趣在学,已经对竞赛失去信心了的样子,我还是回去跪跪文化课吧QAQ 第一道环套树DP...其实思想挺简单的,就把环拆开,分类处理.若拆成开的 ...

  4. 【BZOJ1040】[ZJOI2008] 骑士(基环外向树DP)

    点此看题面 大致题意: 给你一片基环外向树森林,如果选定了一个点,就不能选择与其相邻的节点.求选中点的最大权值和. 树形\(DP\) 此题应该是 树形\(DP\) 的一个升级版:基环外向树\(DP\) ...

  5. 【bzoj1040】[ZJOI2008]骑士 并查集+基环树dp

    题目描述 Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在 ...

  6. BZOJ1040:骑士(基环树DP)

    Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在和平环境中 ...

  7. 基环树DP

    基环树DP Page1:问题 啥是基环树?就是在一棵树上增加一条边. Page2:基环树的几种情况 无向 有向:基环外向树,基环内向树. Page3:处理问题的基本方式 1.断环成树 2.分别处理树和 ...

  8. [BZOJ1791][IOI2008]Island岛屿(环套树DP)

    同NOI2013快餐店(NOI出原题?),下面代码由于BZOJ栈空间过小会RE. 大致是对每个连通块找到环,在所有内向树做一遍DP,再在环上做两遍前缀和优化的DP. #include<cstdi ...

  9. 2018牛客网暑期ACM多校训练营(第二场):discount(基环树DP)

    题意:有N个不同的商品,每个商品原价是Pi元,如果选择打折,可以减少Di元.  现在加一种规则,每个商品有一个友好商品Fai,如果i用原价买,则可以免费买Fai. 现在问买到所有物品的最小价格. 思路 ...

随机推荐

  1. 【个人训练】(UVa146)ID Codes

    题意与解析 这题其实特别简单,求给定排列的后继.使用stl(next_permutation)可以方便地解决这个问题.但是,想要自己动手解就是另外一回事了.我的解法是从后往前找到第一个$a_i$比$a ...

  2. CCF-NOIP-2018 提高组(复赛) 模拟试题(五)

    T1 相遇 [问题描述] 在一场奇怪的梦里,小 Y 来到了一个神奇的国度.这个国度可以用一根数轴表示,小 Y 在 N 处,而小 Y 想吃的美食在 K 处.小 Y 有两种方式移动, 一种叫做步行, 一种 ...

  3. 最短路径——Bellman-Ford算法

    一.相关定义 最短路径:求源点到某特定点的最短距离 特点:Bellman-Ford算法主要是针对有负权值的图,来判断该图中是否有负权回路或者存在最短路径的点 局限性:算法效率不高,不如SPFA算法 时 ...

  4. Python中enumerate函数用法详解

    enumerate函数用于遍历序列中的元素以及它们的下标,多用于在for循环中得到计数,enumerate参数为可遍历的变量,如 字符串,列表等 一般情况下对一个列表或数组既要遍历索引又要遍历元素时, ...

  5. beta版本冲刺六

    目录 组员情况 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:恺琳 组员6:翟丹丹 组员7:何家伟 组员8:政演 组员9:黄鸿杰 组员10:刘一好 组员11:何宇恒 展示组内最新成果 团队签入记 ...

  6. DDD-领域驱动设计

    识别领域事件 DDD战术篇:领域模型的应用 DDD战略篇:架构设计的响应力 DDD实战篇:分层架构的代码结构

  7. 安装全局webpack

    npm ls webpack 和npm ls webpack -g 查看本地和全局版本 npm install webpack@1.15.0 -g 全局 然后到项目里面 npm install npm ...

  8. 关于Maven项目install时出现No compiler is provided in this environment的处理

    关于Maven项目build时出现No compiler is provided in this environment的处理 新配置的Eclipse环境,运行现有项目没问题,一日,从svn上检出了一 ...

  9. HDU3488:Tour(KM算法)

    Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submis ...

  10. Install the Active Directory Administration Tools on Windows Server

    安装 Active Directory 管理工具 To manage your directory from an EC2 Windows instance, you need to install ...