1040: [ZJOI2008]骑士

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 2275 Solved: 872
[Submit][Status][Discuss]
Description

Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英。他们劫富济贫,惩恶扬善,受到社会各界的赞扬。最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争。战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队。于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶。骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾。每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶的人一同出征的。战火绵延,人民生灵涂炭,组织起一个骑士军团加入战斗刻不容缓!国王交给了你一个艰巨的任务,从所有的骑士中选出一个骑士军团,使得军团内没有矛盾的两人(不存在一个骑士与他最痛恨的人一同被选入骑士军团的情况),并且,使得这支骑士军团最具有战斗力。为了描述战斗力,我们将骑士按照1至N编号,给每名骑士一个战斗力的估计,一个军团的战斗力为所有骑士的战斗力总和。

Input

第一行包含一个正整数N,描述骑士团的人数。接下来N行,每行两个正整数,按顺序描述每一名骑士的战斗力和他最痛恨的骑士。

Output

应包含一行,包含一个整数,表示你所选出的骑士军团的战斗力。

Sample Input

3

10 2

20 3

30 1
Sample Output

30
HINT

对于100%的测试数据,满足N ≤ 1 000 000,每名骑士的战斗力都是不大于 1 000 000的正整数。

题解:这道题是一个环套森林,顺便学了一下怎样在一个环上dp。
其实我们如果抛去环不看的话,这道题是比较简单的,跟poj上的一道树形dp时一样的,都是在父节点和子节点上选一个的问题。
那么我们再来看环的问题,对于环我们其实可以将环拆成两条链来做,一个是强制不取最后一个元素,另一个是强制不取第一个元素。
在找到每一环的时候,我们先对环上的树进行dp。

f[i][0]=∑(ftree[son][0],ftree[son][1])表示不选第i个点。

f[i][0]=\sum(ftree[son][0],ftree[son][1]) 表示不选第i个点。

f[i][1]=∑(ftree[son][0])+v[i]表示选第i个点。

f[i][1]=\sum(ftree[son][0] ) +v[i] 表示选第i个点。
这样处理完环上的树以后,再来处理环。
其实处理环也很简单,分成两种情况取最大值就好了。
chain[i]数组记录环上的元素。
fchain[i][0]=max(f[i-1][0],f[i-1][1])+ftree[chain[i]][0];
fchian[i][1]=f[i-1][0]+ftree[chain[i]][1];
然后就行了。。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1000010;
int point[N],next[N],tot=1,fa[N],v[N],n,son[N],chain[N];
long long ftree[N][2]={0},fchain[N][4],ans=0,maxn=0;
bool use[N];
struct S{int st,en;
}aa[N];
void add(int x,int y)
{tot+=1;next[tot]=point[x];point[x]=tot;aa[tot].st=x;aa[tot].en=y;
}
void dptree(int x)
{int i;use[x]=false;ftree[x][0]=0; ftree[x][1]=v[x];for(i=point[x];i;i=next[i]){dptree(aa[i].en);ftree[x][0]+=max(ftree[aa[i].en][0],ftree[aa[i].en][1]);ftree[x][1]+=ftree[aa[i].en][0];}
}
void dpchain()
{int i;maxn=0;fchain[1][0]=ftree[chain[1]][0];fchain[1][1]=ftree[chain[1]][1];for(i=2;i<=chain[0];++i){fchain[i][0]=max(fchain[i-1][0],fchain[i-1][1])+ftree[chain[i]][0];fchain[i][1]=fchain[i-1][0]+ftree[chain[i]][1];}maxn=fchain[chain[0]][0];fchain[1][0]=ftree[chain[1]][0];fchain[1][1]=ftree[chain[1]][0];for(i=2;i<=chain[0];++i){fchain[i][0]=max(fchain[i-1][0],fchain[i-1][1])+ftree[chain[i]][0];fchain[i][1]=fchain[i-1][0]+ftree[chain[i]][1];}maxn=max(maxn,max(fchain[chain[0]][1],fchain[chain[0]][0]));
}
int main()
{int i,j,x,y,k,now;scanf("%d",&n);memset(use,1,sizeof(use));for(i=1;i<=n;++i){scanf("%d%d",&x,&y);v[i]=x;fa[i]=y;add(y,i);}/*------dp-------*/for(i=1;i<=n;++i){if(!use[i]) continue;k=i;chain[0]=0;while(use[k]){use[k]=false;k=fa[k];son[fa[k]]=k;}now=k;while(1){ftree[k][1]=v[k];for(j=point[k];j;j=next[j]){if(aa[j].en!=son[k]){dptree(aa[j].en);ftree[k][0]+=max(ftree[aa[j].en][0],ftree[aa[j].en][1]);ftree[k][1]+=ftree[aa[j].en][0];}}//cout<<ftree[k][1]<<' '<<ftree[k][0]<<endl;chain[0]+=1;chain[chain[0]]=k;k=fa[k];if(k==now) break;}dpchain();ans+=maxn;}cout<<ans<<endl;
}

【bzoj1040】【ZJOI2008】【骑士】相关推荐

  1. BZOJ1040: [ZJOI2008]骑士

    1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 5332  Solved: 2023 [Submit][Stat ...

  2. bzoj1040(ZJOI2008)骑士——基环树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1040 基环树的模板. 套路就是把环断开,先把一端作为根节点,强制不选:再把另一端作为根节点, ...

  3. 1584 ZJOI2008 骑士

    首先声明:下面是关于这道题的某位大佬博主的解答代码作解释,代码出处为1584 ZJOI2008 骑士(Bzoj1040 LOJ10162 LUOGU2607 省选/NOI-) 枚举组合数30分 类01 ...

  4. bzoj 1040: [ZJOI2008]骑士 树形dp

    题目链接 1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3054  Solved: 1162 [Submit] ...

  5. P2607 [ZJOI2008]骑士

    P2607 [ZJOI2008]骑士 题意: n个点n个边,每个点都有权值,相邻的点不能同时选择,问如何选择能使得权值最大 题解: 这个题很有P1352 没有上司的舞会这个题的感觉,唯一的区别是那个题 ...

  6. 基环树DP(bzoj 1040: [ZJOI2008]骑士)

    树:n个点n-1条边的连通图 基环树:n个点n条边的连通图,也就是一个环套着多棵树 基环树DP:找到环上任意相邻两点,断掉这两点之间的边,就形成了一棵树 之后对这两点分别进行一次树形DP即可 例题: ...

  7. bzoj 1040 1040: [ZJOI2008]骑士

    1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 5210  Solved: 1987 [Submit][Stat ...

  8. bzoj 1040: [ZJOI2008]骑士

    第一次做环套树的题 这道题题目中貌似是有向边,实际上想一想就知道是无向的. 因为一个骑士觉得另一个骑士丑他们俩就走不到一起. 所以整个图实际上是一个无向环套树森林. 对于每一棵环套树,先dfs找环,找 ...

  9. 1040: [ZJOI2008]骑士

    Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 7113  Solved: 2797 [Submit][Status][Discuss] Descri ...

  10. LOI 2607 [ZJOI2008]骑士

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

最新文章

  1. 《系统集成项目管理工程师》必背100个知识点-71合同变更控制系统
  2. CentOS安装Mysql8
  3. java 线程同时启动_java多个线程同时启动的两种方式
  4. .data()与.detach()的区别
  5. 我身边的计算机网,电脑在我身边作文700字
  6. nutz 自定义sql的使用
  7. tf.nn.sigmoid_cross_entropy_with_logits 分类
  8. PaddleNLP Taskflow
  9. 64位计算机可以安装xp,64位xp系统如何安装【图解】
  10. Centos7通过oh-my-zsh安装powerlevel9k和powerlevel10k
  11. JAVA面试题目及推荐书籍
  12. wps打开pdf乱码_用wps2016版打开word文件乱码怎么处理
  13. 北京科技大学计算机专业选课要求,2020年北京科技大学在北京招生专业选科要求对照表...
  14. 图像处理-1 带色彩恢复的多尺度视网膜增强算法
  15. 看黑客如何一步步攻破你的服务器
  16. 嵌入式远程岗位、兼职、接单、众包平台
  17. 001-eNSP 先学画个漂亮的拓扑图
  18. verilog “function”函数一直报错解决办法
  19. qbo机器人软件总体情况
  20. MBT测试实例:做个“机器人”,使其随机、持续的对“web页面”做交互性测试--补充篇1一些思考

热门文章

  1. “正被停用的激活上下文不是最近激活的”的错误的解决
  2. 解决word文档网格设置每行36字符数但显示32个字
  3. 如何使用 PowerShell 锁定、解锁、启用和禁用 AD 帐户
  4. 史上最全!56个JavaScript的「手写」知识点,扫盲啦!
  5. 如何在 Ubuntu 上使用 AppImage 软件镜像包?
  6. Excel通过poi设置折线图样式
  7. 高等数学学习笔记——第二十八讲——函数的极值及最优化应用
  8. 2020神舟几号发射_中国宇宙飞船发射到神州几号了
  9. map方法的常见使用
  10. 工业机器人码垛教学实施_工业机器人码垛方案设计