N个点,每个点发出一条边,那么这个图的形状一定是一个基环树森林(如果有重边就会出现森林)

那我做f[0][x]和f[1][x]分别表示对于x子树,x这个点选还是不选所带来的最大价值

然后就变成了这好几个环上不能选相邻的点,最大的价值和

我们把这个环从N到1处断开,然后钦定一下1选还是不选,统计一下答案就可以了。

 #include<bits/stdc++.h>
#define pa pair<int,int>
#define ll long long
using namespace std;
const int maxn=; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int N;
int eg[maxn*][],egh[maxn],ect;
int dep[maxn],fa[maxn];
int root[maxn][],pct,rh[maxn],rct;
int stk[maxn],top[maxn];
ll f[][maxn];
bool flag[maxn],isroot[maxn],connected[maxn]; inline void adeg(int a,int b){
eg[++ect][]=b;eg[ect][]=egh[a];egh[a]=ect;
}
inline void adrot(int a,int b){
root[++rct][]=b;root[rct][]=rh[a];rh[a]=rct;
} void dfs1(int ii,int x){
flag[x]=;
//printf("%d %d %d\n",x,fa[x],dep[x]);
for(int i=egh[x];i!=-;i=eg[i][]){
int b=eg[i][];if(b==fa[x]) continue;
//printf("#%d %d %d %d %d\n",x,b,flag[b],i,eg[i][1]);
if(flag[b]){
if(connected[ii]) continue;
int u=x,v=b,lca,cnt=;
if(dep[u]<dep[v]) swap(u,v);
while(dep[u]!=dep[v]) adrot(ii,u),isroot[u]=,u=fa[u];
while(u!=v){
isroot[u]=isroot[v]=;
adrot(ii,u);
stk[++cnt]=v;
u=fa[u];v=fa[v];
}lca=u;isroot[lca]=;adrot(ii,lca);
for(int j=cnt;j;j--) adrot(ii,stk[j]);
connected[ii]=;
}else{
dep[b]=dep[x]+;fa[b]=x;
dfs1(ii,b);
}
}
} void dfs2(int x,int F){
for(int i=egh[x];i!=-;i=eg[i][]){
int b=eg[i][];if(b==F||isroot[b]) continue;
dfs2(b,x);
f[][x]+=max(f[][b],f[][b]);
f[][x]+=f[][b];
}
} inline ll solve(int p){
if(rh[p]==-) return max(f[][top[p]],f[][top[p]]);
ll re=;
ll g1=f[][root[rh[p]][]],g0=;
for(int i=root[rh[p]][];i!=-;i=root[i][]){
ll xx=max(g0,g1);
g1=g0+f[][root[i][]];
g0=xx+f[][root[i][]];
}re=max(re,g0); g1=,g0=f[][root[rh[p]][]];
for(int i=root[rh[p]][];i!=-;i=root[i][]){
ll xx=max(g0,g1);
g1=g0+f[][root[i][]];
g0=xx+f[][root[i][]];
}re=max(re,max(g0,g1));
return re;
} int main(){
int i,j,k;
//freopen("2607.in","r",stdin);
N=rd();memset(egh,-,sizeof(egh));
for(i=;i<=N;i++){
int a=rd(),b=rd();
f[][i]=a;
adeg(i,b);adeg(b,i);
}memset(rh,-,sizeof(rh));
for(i=;i<=N;i++){
if(!flag[i]) top[++pct]=i,dfs1(pct,i);
}
//for(i=1;i<=rct;i++) printf("!%d %d %d\n",i,root[i][0],root[i][1]);
for(i=;i<=rct;i++) dfs2(root[i][],);
ll ans=;
for(i=;i<=pct;i++){
ans+=solve(i);
}
printf("%lld\n",ans); return ;
}

luogu2607/bzoj1040 [ZJOI2008]骑士 (基环树形dp)的更多相关文章

  1. [BZOJ1040][ZJOI2008]骑士 基环树DP

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1040 题目给出了$n$个点和$n$条无向边,即一棵基环树或者基环树森林. 如果题目给的关系 ...

  2. 2018.11.06 bzoj1040: [ZJOI2008]骑士(树形dp)

    传送门 由题可知给出的是基环森林. 因此对于每个基环森林找到环断开dpdpdp两次就行了. 代码: #include<bits/stdc++.h> using namespace std; ...

  3. BZOJ_1040_[ZJOI2008]骑士_树形DP

    BZOJ_1040_[ZJOI2008]骑士_树形DP 题意: Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各 界的赞扬.最近发生了一件可怕的事情,邪 ...

  4. [bzoj1040][ZJOI2008]骑士_树形dp_基环树_并查集

    骑士 bzoj-1040 ZJOI-2008 题目大意:n个骑士,每个骑士有权值val和一个讨厌的骑士.如果一个骑士讨厌另一个骑士那么他们将不会一起出战.问出战的骑士最大atk是多少. 注释:$1\l ...

  5. 【洛谷】2607: [ZJOI2008]骑士【树形DP】【基环树】

    P2607 [ZJOI2008]骑士 题目描述 Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬. 最近发生了一件可怕的事情,邪恶的Y国发动了一 ...

  6. BZOJ1040 [ZJOI2008]骑士 基环树林(环套树) 树形动态规划

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题意概括 有n个人,每一个人有一个最恨的人. 并且,每一个人有一个权值. 一个人不可以和他最恨的人同时被选中. 现在请你求出在 ...

  7. [ZJOI2008] 骑士 - 基环树dp

    一类基环树dp都是这个套路吧 随便拆掉环上的一条边 然后跑树形dp,设\(f[i][0/1]\)表示以第\(i\)个人为根的子树,第\(i\)个人选或不选,能收获的最大值 以断点\(u,v\)为根分别 ...

  8. [BZOJ1040][ZJOI2008]骑士(环套树dp)

    1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 5816  Solved: 2263[Submit][Status ...

  9. BZOJ1040: [ZJOI2008]骑士 树套环DP

    题意:一个图n个点n条边保证点能互相到达,ab有边意味着ab互相厌恶,求一个集合,使得集合里元素最多而且没有人互相厌恶 删去环上一条边树形dp,比如删掉的边连着a,b,那么先dp出不选a的最大值,再d ...

随机推荐

  1. [尝鲜]妈妈再也不用担心 dotnet core 程序发布了: .NET Core Global Tools

    什么是 .NET Core Global Tools? Global Tools是.NET Core 2.1 中一个初次出现的特性.Global Tools提供了一种方法,让开发人员编写的.NET C ...

  2. sudo 与输出重定向

    本文介绍如何使用 sudo 将输出重定向到当前用户没有权限的文件.注意:本文中 demo 的演示环境为 ubuntu 18.04. Permission denied 问题 如果当前用户没有某个文件的 ...

  3. 如何在命令长度受限的情况下成功get到webshell(函数参数受限突破、mysql的骚操作)

    0x01 问题提出 还记得上篇文章记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门),我们讲到了一些PHP的一些如何巧妙地绕过数字和字母受限的技巧,今天我要给大家分享的是如 ...

  4. Python下操作Memcache/Redis/RabbitMQ说明

    一.MemcacheMemcache是一套分布式的高速缓存系统,由LiveJournal的Brad Fitzpatrick开发,但目前被许多网站使用以提升网站的访问速度,尤其对于一些大型的.需要频繁访 ...

  5. java注解XML

    用的是jdk自带的javax.xml.bind.JAXBContext将对象和xml字符串进行相互转换. 比较常用的几个: @XmlRootElement:根节点 @XmlAttribute:该属性作 ...

  6. 如何利用Android Studio打包React Native APK

    ok!百度出来的东西很杂,所以,这里介绍一种最简单,最合适我们(新手,应该是吧)的APK的打包方式! 当然!这种打包是基于Android Studio的,所以,注意喽!!!! 废话不多说开始吧! 首先 ...

  7. v-for v-if || v-else

    <el-col> <div v-for="item in resultDetail" class="physical-content" v-i ...

  8. 腾讯QQ的商业模式

    近期听到许多关于腾讯QQ的报道,然后想到之前自己在QQ上遇到的一些问题,一瞬间感觉大脑的所有想法喷涌而出. 以前总觉得QQ是个很好的平台,我们可以通过QQ和自己的亲人朋友爱人聊天,有时候还可以在自己的 ...

  9. Linux内核第八节 20135332武西垚

    第一种分类: I/O-bound:频繁进行I/O,并且需要花费很多时间等待I/O完成 CPU-bound:计算密集,需要大量的CPU时间进行运算 第二种分类: 批处理进程:不必与用户交互,常在后台进行 ...

  10. github第一次作业链接

    https://github.com/xuhuzi/test/blob/master/test1 https://github.com/xuhuzi/test/blob/master/test2 ht ...