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. 线段树简单入门 (含普通线段树, zkw线段树, 主席树)

    线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...

  2. 初探 Qt Opengl【2】

    最近在研究QOPengl QGraphicsView QGraphicsItemQGraphicsScene不过也只是皮毛,也不是做什么技术贴,就是记录一下自己在其中遇到的问题,和自己新学到的东西. ...

  3. TortoiseSVN的安装使用

    下面分享一篇关于TortoiseSVN的安装以及使用 1.运行TortoiseSVN-1.6.6.17493-win32-svn-1.6.6.msi程序, 开始安装 2.点击Next, 下一步 3.选 ...

  4. APP功能性测试-4

    弱网络测试 使用fiddler模拟低速环境 使用fiddler抓取手机上某个应用的包 手机连接fiddler fiddler 代理地址127.0.0.1默认端口8888 只抓http协议(https, ...

  5. Linux SPI总线和设备驱动架构之二:SPI通用接口层

    通过上一篇文章的介绍,我们知道,SPI通用接口层用于把具体SPI设备的协议驱动和SPI控制器驱动联接在一起,通用接口层除了为协议驱动和控制器驱动提供一系列的标准接口API,同时还为这些接口API定义了 ...

  6. Mininet实验 基于Mininet测量路径的损耗率

    实验原理 在SDN环境中,控制器可以通过对交换机下发流表操作来控制交换机的转发行为,此外,还可以利用控制器测量路径的损耗率.在本实验中,基于Mininet脚本,设置特定的交换机间的路径损耗速率,然后编 ...

  7. STL中mem_fun与mem_fun_ref的区别[转]

    http://www.cnblogs.com/Purple_Xiapei/archive/2012/05/27/2520483.html STL中mem_fun和mem_fun_ref的用法 分类:  ...

  8. Intellij Idea 创建Web项目入门

    相关软件: Intellij Idea14:http://pan.baidu.com/s/1nu16VyD JDK7:http://pan.baidu.com/s/1dEstJ5f Tomcat(ap ...

  9. Chromium之文件类型

    .grp: Generate your project. 是由Json(JavaScript Object Notation)(or Python?)来解析,根据环境(OS,Compiler..)来生 ...

  10. 玩Vim

    1)我一个脚本中粘贴的都是当年在vim下粘的东西,都是带行号的,我现在想把所有的行号都换成回车键,要怎么办呢? %s/[0-9]/^M/g 注:其中回车在vim的输入方法是ctrl+V,会得到^,此时 ...