BZOJ 1040 [ZJOI2008]骑士 (基环树+树形DP)
<题目链接>
题目大意:
Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英。他们劫富济贫,惩恶扬善,受到社会各界的赞扬。最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争。战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队。于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶。骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾。每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶的人一同出征的。战火绵延,人民生灵涂炭,组织起一个骑士军团加入战斗刻不容缓!国王交给了你一个艰巨的任务,从所有的骑士中选出一个骑士军团,使得军团内没有矛盾的两人(不存在一个骑士与他最痛恨的人一同被选入骑士军团的情况),并且,使得这支骑士军团最具有战斗力。为了描述战斗力,我们将骑士按照1至N编号,给每名骑士一个战斗力的估计,一个军团的战斗力为所有骑士的战斗力总和。
解题分析:
比较经典的基环树(环套树)。本题给出一个$n$条边$n$个点的有向图,我们可以发现,因为本题有向边表示这两个人至多只能出现其中一个,是用来表示一种关系的,所以在实际意义上,完全可以用无向边来代替。于是,本题就转化成了基环树森林,基环树的主要突破口就是要找出每个基环树的环(每个连通分量都是一颗基环树),然后将环中的一条边拆掉,使其变成一棵树,分别以拆掉的边的两个端点作为树的根,然后进行树形DP。本题就变成了对于树上有关系的两个点,只能选一个,使得最后的总价值最大,这就变成了一个比较经典的树形DP模型(比如上司的舞会)。
注意拆环的时候,强制一个点为根,并且不选,因为尽管我们拆除了那条边,但它还是正实存在的,所以只有不选的状态才能避免这两个点都被选中(防止违反题意)。
#include <bits/stdc++.h>
using namespace std; #define clr(a,b) memset(a,b,sizeof(a))
#define REP(i,s,t) for(int i=s;i<=t;i++)
const int N = 1e6+;
typedef long long ll;
struct Edge{ int to,nxt; }e[N<<];
int n,m,cnt,head[N];
int Ecut,rt,urt;
int w[N],vis[N];
ll dp[N][]; inline void init(){
cnt=;clr(head,-);clr(vis,);clr(dp,);
}
inline void add(int u,int v){ e[cnt]=(Edge){ v,head[u] };head[u]=cnt++; } void dfs(int u,int pre){
vis[u]=;
for(int i=head[u];~i;i=e[i].nxt){
int v=e[i].to;
if(v==pre)continue;
if(!vis[v])dfs(v,u);
else { //如果找到环了
rt=u,urt=v,Ecut=i; //记录下这个环的两个端点,并且记录这个拆除的边
}
}
}
void trdp(int u,int pre){
dp[u][]=w[u]; //表示选当前这个点的价值
dp[u][]=; //表示不选当前这个点的价值
for(int i=head[u];~i;i=e[i].nxt){
int v=e[i].to;
if(i==Ecut || i==(Ecut^) || v==pre)continue;
trdp(v,u);
dp[u][]+=dp[v][];
dp[u][]+=max(dp[v][],dp[v][]);
}
}
int main(){
while(~scanf("%d",&n)){
init();
REP(i,,n){
int now;scanf("%d%d",&w[i],&now);
add(i,now);add(now,i);
}
ll sum=;
REP(i,,n) if(!vis[i]) {
dfs(i,-); //基环树森林,每个连通分量中必有一个环
trdp(rt,-); //以拆分的两个点分别为根,进行树形DP
ll tmp = dp[rt][];
trdp(urt,-);
sum+=max(tmp,dp[urt][]);
}
printf("%lld\n",sum);
}
}
BZOJ 1040 [ZJOI2008]骑士 (基环树+树形DP)的更多相关文章
- BZOJ 1040: [ZJOI2008]骑士 基环加外向树
1040: [ZJOI2008]骑士 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1190 Solved: 465[Submit][Status] ...
- bzoj 1040: [ZJOI2008]骑士 環套樹DP
1040: [ZJOI2008]骑士 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1755 Solved: 690[Submit][Status] ...
- BZOJ 1040 骑士 基环树 树形DP
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1040 题目大意: Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫 ...
- day 2 下午 骑士 基环树+树形DP
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #inc ...
- 洛谷 P1453 城市环路 ( 基环树树形dp )
题目链接 题目背景 一座城市,往往会被人们划分为几个区域,例如住宅区.商业区.工业区等等.B市就被分为了以下的两个区域--城市中心和城市郊区.在着这两个区域的中间是一条围绕B市的环路,环路之内便是B市 ...
- bzoj 1040: [ZJOI2008]骑士 树形dp
题目链接 1040: [ZJOI2008]骑士 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3054 Solved: 1162[Submit][S ...
- BZOJ 1040: [ZJOI2008]骑士 [DP 环套树]
传送门 题意:环套树的最大权独立集 一开始想处理出外向树树形$DP$然后找到环再做个环形$DP$ 然后看了看别人的题解其实只要断开环做两遍树形$DP$就行了...有道理! 注意不连通 然后洛谷时限再次 ...
- [BZOJ 1040][ZJOI2008]骑士
1040: [ZJOI2008]骑士 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 5403 Solved: 2060[Submit][Status ...
- Bzoj 1040 [ZJOI2008]骑士 题解
1040: [ZJOI2008]骑士 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 5368 Solved: 2044[Submit][Status ...
随机推荐
- 构建LNMP+memcached服务
通过PHP页面实现对memcached服务器的数据操作,实现以下目标: - 为PHP安装memcache扩展 - 创建PHP页面,并编写PHP代码,实现对memcached的数据操作 环境:部署LNM ...
- 树——populating-next-right-pointers-in-each-node(填充每个节点的next指针)
问题: Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode ...
- [sql 注入] 注入类型
基于整型的注入: url:http://localhost/?id=12 拼接sql:$sql = "select * from user where id = {$_GET['id']}& ...
- [web 安全] 源码泄露
web 源码泄露 1..hg 源码泄露 http://www.example.com/.hg/ 2..git 源码泄露 http://www.example.com/.git/config 3..ds ...
- maven 自动编译脚本
在maven工程根目录创建windows批处理脚本文件,例如tool.bat,内容如下 @echo off color 1f :menu echo -------------------------- ...
- man fdisk
FDISK(8) Linux Programmer?. Manual/Linux程序手册 FDISK(8) NAME/名称 fdisk - Partition ta ...
- 转载-使用Nodepad++来编辑我们服务器的配置文件
转自------------------ 作者:李阿昀 来源:CSDN 原文:https://blog.csdn.net/yerenyuan_pku/article/details/73128819 ...
- PL/SQL 循环
----PL/SQL基本循环语句 LOOP DECLARE x ; BEGIN LOOP dbms_output.put_line(x); x :; THEN exit; END IF; END LO ...
- BZOJ 1596: [Usaco2008 Jan]电话网络 树形DP
挺经典的,细节需要特别注意一下 Code: #include<bits/stdc++.h> using namespace std; #define setIO(s) freopen(s& ...
- BZOJ 4407: 于神之怒加强版 莫比乌斯反演 + 线筛积性函数
Description 给下N,M,K.求 Input 输入有多组数据,输入数据的第一行两个正整数T,K,代表有T组数据,K的意义如上所示,下面第二行到第T+1行,每行为两个正整数N,M,其意 ...