洛谷P2607 [ZJOI2008]骑士(树形dp)

题目描述

Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英。他们劫富济贫,惩恶扬善,受到社会各界的赞扬。

最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争。战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队。于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶。

骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾。每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶的人一同出征的。

战火绵延,人民生灵涂炭,组织起一个骑士军团加入战斗刻不容缓!国王交给了你一个艰巨的任务,从所有的骑士中选出一个骑士军团,使得军团内没有矛盾的两人(不存在一个骑士与他最痛恨的人一同被选入骑士军团的情况),并且,使得这支骑士军团最具有战斗力。

为了描述战斗力,我们将骑士按照1至N编号,给每名骑士一个战斗力的估计,一个军团的战斗力为所有骑士的战斗力总和。

输入输出格式

输入格式:

输入文件knight.in第一行包含一个正整数N,描述骑士团的人数。

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

输出格式:

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

输入输出样例

输入样例#1: 复制

3
10 2
20 3
30 1

输出样例#1: 复制

30

说明

对于30%的测试数据,满足N ≤ 10;

对于60%的测试数据,满足N ≤ 100;

对于80%的测试数据,满足N ≤ 10 000。

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

看到标签是树形DP就点进来了

可没想到这题给了一个图??

不过冷静下来,我们不难发现,这张图实际上只有一个环,也就是传说中的基环树

因此我们按照套路,把一条环上的边破坏掉,然后对两棵独立的树做树形DP

设$f[i][0/1]$表示该节点是否选择时的最大价值

转移的时候枚举孩子是否选择

不过在BZOJ上死活RE

// luogu-judger-enable-o2
#include<cstdio>
#include<vector>
#include<cstring>
#define LL long long 
#define Pair pair<int,int>
using namespace std;
const int MAXN=3*1e6+10;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<22,stdin),p1==p2)?EOF:*p1++)
char buf[1<<22],*p1=buf,*p2=buf;
inline int read() {
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
struct Edge {
    int u, v, nxt;
}edge[MAXN];
int head[MAXN], num=0;
void AddEdge(int x,int y) {
    edge[num] = (Edge){x, y, head[x]};
    head[x] = num++;
} 
int val[MAXN], vis[MAXN], BeginEdge;
LL f[MAXN][2];
Pair Begin;
void FindCircle(int now,int fa) {
    vis[now] = 1;
    for(int i = head[now];i != -1;i = edge[i].nxt) {
        if( (i ^ 1) == fa) continue;
        if(vis[ edge[i].v ]) {BeginEdge = i;Begin.first = now;Begin.second = edge[i].v;continue ;}
        FindCircle(edge[i].v, i);
    }
}
LL Dp(int now,int fa) {
    f[now][0] = 0;
    f[now][1] = val[now];
    for(int i = head[now];i != -1;i = edge[i].nxt) {
        if((i ^ 1) == fa) continue;
        if((i == BeginEdge) || ((i ^ 1) == BeginEdge)) continue;
        Dp(edge[i].v, i);
        f[now][0] += max(f[edge[i].v][1], f[edge[i].v][0]);
        f[now][1] += f[edge[i].v][0];
    }
    return f[now][0];
}
int main() {
    #ifdef WIN32
    freopen("a.in","r",stdin);
    #endif
    int N = read();
    memset(head, -1, sizeof(int) * N *4);
    for(register int i=1;i<=N;i++) {
        val[i] = read();
        int x = read();
        AddEdge(i,x),AddEdge(x,i);
    }
    long long  ans = 0;
    for(register int i=1;i<=N;i++) {
        if(!vis[i]) {
            FindCircle(i,-2);
            ans += max(Dp(Begin.first,-1),Dp(Begin.second,-1));
        }
    }
    printf("%lld", ans);
    return 0;
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Vamei实验室

Python补充06 Python之道

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢!

1132
来自专栏高性能服务器开发

携程面试题

冬天,西风凛冽,天空阴沉,行人都急匆匆的奔走,到了家,烤着炉子,外边洋洋洒洒的下起了雪。知道什么是“晚来天欲雪”,什么是“红泥小火炉”。

4123
来自专栏数据结构与算法

BZOJ1061: [Noi2008]志愿者招募(线性规划)

  申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管。布布刚上任就遇到了一个难

1514
来自专栏HansBug's Lab

1934: [Shoi2007]Vote 善意的投票

1934: [Shoi2007]Vote 善意的投票 Time Limit: 1 Sec  Memory Limit: 64 MB Submit: 1174  ...

2917
来自专栏ml

HDUOJ---1236 排名(浙大考研题)

排名 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/O...

2433
来自专栏数据结构与算法

1010. 邮寄包裹

1010. 邮寄包裹 (Standard IO) 时间限制: 1000 ms  空间限制: 262144 KB  具体限制  题目描述 某邮局对邮寄包裹有如下...

42011
来自专栏Python攻城狮

Python之禅

在Python交互式解释器中输 入import this就会显示Tim Peters的The Zen of python

1121
来自专栏Vamei实验室

“不给力啊,老湿!”:RSA加密与破解

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢!

5281
来自专栏C语言及其他语言

【每日一题】问题 1146: 舍罕王的失算

关注我们 题目描述 相传国际象棋是古印度舍罕王的宰相达依尔发明的.舍罕王十分喜爱象棋,决定让宰相自己选择何种赏赐.这位聪明的宰相指着8*8共64格的象棋说:陛...

35111
来自专栏蜉蝣禅修之道

LeetCode之Climbing Stairs与斐波那契数列的联想

1694

扫码关注云+社区

领取腾讯云代金券