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,拆环,记录拆的两点,强制两点中一点为根,且不选跑DP,再强制另一点为根不选跑DP,取大
遇到一个问题,就是环由两个构成怎么办,我的解决方案是使他们不成环直接跑DP,结果常数超大,代码特丑
 #include<cstdio>
#include<iostream>
#include<cstring>
#define ll long long
using namespace std;
const int N=;
int q[N],du[N],v[N],c[N],deep[N],fa[N],head[N],sz[N];
int root,other,cnt,n,tot;
ll ans,end,tr[N][];
bool vis[N],pd[N],viss[N];
struct ee{int to,next;}e[N*];
void ins(int u,int v){
e[++cnt].next=head[u],e[cnt].to=v,head[u]=cnt;du[u]++;
e[++cnt].next=head[v],e[cnt].to=u,head[v]=cnt;du[v]++;
}
void topsort(){
int l,r;l=r=;
for (int i=;i<=n;i++) if(du[i]==) q[++r]=i,vis[i]=;
while(l<r){
int now=q[++l];
for(int i=head[now];i;i=e[i].next){
int v=e[i].to;
if(du[v]>){
du[v]--;
if(du[v]==) q[++r]=v,vis[v]=;
}
}
}
} void dfs(int x,int t){
vis[x]=t;c[x]=t;
for (int i=head[x];i;i=e[i].next){
int v=e[i].to;
if(!vis[v]) dfs(v,t);
}
} ll treedp(int x,int bz,int t){
if(tr[x][bz]!=-) return tr[x][bz];
ll mid=;bool flag=;viss[x]=;
for(int i=head[x];i;i=e[i].next){
int vv=e[i].to;
if(deep[vv]==deep[x]+) {
flag=;
if(bz==)mid+=max(treedp(vv,bz^,t),treedp(vv,bz,t));
else mid=mid+treedp(vv,bz^,t);
}
}
if(bz==) mid+=v[x];
if(!flag)tr[x][bz]=bz*v[x];else tr[x][bz]=mid;
return tr[x][bz];
} void solve(int x,int bz,int t){
vis[x]=;
for (int i=head[x];i;i=e[i].next){
int v=e[i].to;
if(x==root&&v==other) continue;
if(!vis[v]) deep[v]=deep[x]+,solve(v,bz,t);
}
} int main(){
scanf("%d",&n);int x;
for(int i=;i<=n;i++){
scanf("%d%d",&v[i],&x);
sz[i]=x; if (sz[x]!=i) ins(i,x);
fa[x]=i;
}
topsort();
for(int i=;i<=n;i++)if(!vis[i]) dfs(i,++tot);
memset(tr,-,sizeof(tr));
for (int i=;i<=n;i++){
if(c[i]&&!pd[c[i]]) {
other=;root=i;deep[root]=;pd[c[i]]=;
for(int j=head[i];j;j=e[j].next){
if(c[e[j].to]==c[i]) {
other=e[j].to;
break;
}
}ans=;
memset(vis,,sizeof(vis));vis[root]=;
solve(root,,c[i]);
ans=max(ans,treedp(root,,c[i]));
root=other;deep[root]=;
other=i;
memset(vis,,sizeof(vis));vis[root]=;
memset(tr,-,sizeof(tr));
solve(root,,c[i]);
ans=max(ans,treedp(root,,c[i]));
end+=ans;
}
}
other=-;
memset(vis,,sizeof(vis));
for(int i=;i<=n;i++) if(!viss[i]) {
root=i;solve(root,,c[i]);
end+=max(treedp(root,,),treedp(root,,));}
printf("%lld",end);
}

【BZOJ 1040】 [ZJOI2008]骑士的更多相关文章

  1. BZOJ 1040: [ZJOI2008]骑士 基环加外向树

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

  2. bzoj 1040: [ZJOI2008]骑士 環套樹DP

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

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

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

  4. [BZOJ 1040][ZJOI2008]骑士

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

  5. Bzoj 1040 [ZJOI2008]骑士 题解

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

  6. [BZOJ 1040] [ZJOI2008] 骑士 【基环+外向树DP】

    题目链接:BZOJ - 1040 题目分析 这道题目的模型就是一个图,不一定联通,每个连通块的点数等于边数. 每个连通块都是一个基环+外向树.即树上增加了一条边. 如果是树,就可以直接树形DP了.然而 ...

  7. bzoj 1040 [ZJOI2008]骑士(基环外向树,树形DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1040 [题意] 给一个基环森林,每个点有一个权值,求一个点集使得点集中的点无边相连且权 ...

  8. BZOJ 1040: [ZJOI2008]骑士(基环树dp)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1040 题意: 思路: 这是基环树,因为每个人只会有一个厌恶的人,所以每个节点只会有一个父亲节点,但是 ...

  9. BZOJ 1040: [ZJOI2008]骑士 | 在基环外向树上DP

    题目: http://www.lydsy.com/JudgeOnline/problem.php?id=1040 题解: 我AC了 是自己写的 超开心 的 考虑断一条边 这样如果根节点不选答案一定正确 ...

  10. BZOJ 1040 [ZJOI2008]骑士 (基环树+树形DP)

    <题目链接> 题目大意: Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的 ...

随机推荐

  1. [改善Java代码]多种最值算法,适时选择

    建议64:多种最值算法,适时选择. 对一批数据进行排序,然后找出其中的最大值或最小值,这是基本的数据结构知识.在Java中我们可以通过编写算法的方式,也可以通过数组先排序再取值的方式来实现.下面以求最 ...

  2. hdu 1358 KMP的next数据运用

    由于next[i]保存的是前i-1个字符中最大的重复子序列,那么i-next[i]就是循环节. #include<cstdio> #include<cstring> #incl ...

  3. poj 2728 最优比率生成树

    思路:设sum(cost[i])/sum(dis[i])=r;那么要使r最小,也就是minsum(cost[i]-r*dis[i]);那么就以cost[i]-r*dis[i]为边权重新建边.当求和使得 ...

  4. asp.net的CascadingDropDown取值和赋值

    获取选择的值 可以使用形如以下的方式获得选择的值: Label1.Text = ddlProvince.SelectedValue;        Label2.Text=ddlCity.Select ...

  5. Commons CLI - Option Properties

    Option Properties The following are the properties that each Option has. All of these can be set usi ...

  6. Ssqlserver 关于Grouping sets

    sqlserver2008之后引入Grouping sets是group by的增强版本,Grouping sets 在遇到多个条件时,聚合是一次性从数据库中取出所有需要操作的数据,在内存中对数据库进 ...

  7. 【转】预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反)

    用VC++ 2008 编写C语言程序,编译出现错误: 预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反) 解决方法: 建工程时 建立空项目 或者在项目设置里关闭预编 ...

  8. Html的maxlength属性

    maxlength表示文本框只能输入的字符串,多的无法输入

  9. ZigBee HomeAutomation分析

    引用请注明出处!联系邮箱是huhao0126@163.com 本例程讲解,基于TI CC2530-2.5.1a中的HomeAutomation文件夹中的SampleLight和SampleSwitch ...

  10. HLG 1400 汽车比赛

    题目链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1400 结构体排序+树状数 ...