[题目链接]

https://www.lydsy.com/JudgeOnline/problem.php?id=1040

[算法]

首先 , 题目中互相讨厌的关系构成了一棵基环森林

用拓扑排序找出环 , 对于每个环上的点为根节点 , 做以下DP :

f[u][0]表示以u为根的子树中 , 不选u , 最大战斗力是多少 , f[u][1]表示选u , 最大战斗力是多少

显然 :

f[u][0] = sigma{max{f[v][0] , f[v][1]})

f[u][1] = a[u] + sigma{f[v][0]}

然后在环上再次DP即可

时间复杂度 : O(N)

[代码]

#include<bits/stdc++.h>
using namespace std;
#define MAXN 1000010
typedef long long LL;
const LL inf = 1e18; struct edge
{
int to , nxt;
} e[MAXN << ]; int n , tot , cnt;
int head[MAXN] , deg[MAXN] , a[MAXN] , c[MAXN];
LL f[MAXN][] , dp[MAXN][];
bool vis[MAXN];
LL ans , res; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
T f = ; x = ;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = (x << ) + (x << ) + c - '';
x *= f;
}
inline void addedge(int u , int v)
{
++tot;
e[tot] = (edge){v , head[u]};
head[u] = tot;
}
inline void topsort()
{
queue< int > q;
for (int i = ; i <= n; i++)
{
if (deg[i] == )
q.push(i);
}
while (!q.empty())
{
int cur = q.front();
q.pop();
for (int i = head[cur]; i; i = e[i].nxt)
{
int v = e[i].to;
if ((--deg[v]) == )
q.push(v);
}
}
}
inline void treedp(int u , int fa)
{
f[u][] = ;
f[u][] = a[u];
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == fa || vis[v]) continue;
treedp(v , u);
f[u][] += max(f[v][] , f[v][]);
f[u][] += f[v][];
}
}
inline void dfs(int u)
{
c[++cnt] = u;
vis[u] = true;
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if (!vis[v] && deg[v] > ) dfs(v);
}
} int main()
{ read(n);
for (int i = ; i <= n; i++)
{
read(a[i]);
int fa;
read(fa);
addedge(i , fa);
addedge(fa , i);
++deg[i]; ++deg[fa];
}
topsort();
for (int u = ; u <= n; u++)
{
if (!vis[u] && deg[u] > )
{
cnt = ;
dfs(u);
} else continue;
for (int i = ; i <= cnt; i++) treedp(c[i] , -);
ans = max(f[c[]][] , f[c[]][]);
for (int i = ; i <= cnt; i++) dp[i][] = dp[i][] = -inf;
dp[][] = f[c[]][];
for (int i = ; i <= cnt; i++)
{
dp[i][] = dp[i - ][] + f[c[i]][];
dp[i][] = max(dp[i - ][] , dp[i - ][]) + f[c[i]][];
}
chkmax(ans , max(dp[cnt][] , dp[cnt][]));
for (int i = ; i <= cnt; i++) dp[i][] = dp[i][] = -inf;
dp[][] = f[c[]][];
for (int i = ; i < cnt; i++)
{
dp[i][] = dp[i - ][] + f[c[i]][];
dp[i][] = max(dp[i - ][] , dp[i - ][]) + f[c[i]][];
}
chkmax(ans , max(dp[cnt - ][] , dp[cnt - ][]) + f[c[cnt]][]);
res += ans;
}
printf("%lld\n" , res); return ; }

[ZJOI 2008] 骑士的更多相关文章

  1. BZOJ 1040 ZJOI 2008 骑士 基环树林+树形DP

    题目大意:有一些骑士.他们每个人都有一个权值.可是因为一些问题,每个骑士都特别讨厌还有一个骑士.所以不能把他们安排在一起.求这些骑士所组成的编队的最大权值和是多少. 思路:首先貌似是有向图的样子,可是 ...

  2. BZOJ 1040 ZJOI 2008 骑士 树形DP

    题意: 有一些战士,他们有战斗力和讨厌的人,选择一些战士,使他们互不讨厌,且战斗力最大,范围1e6 分析: 把战士看作点,讨厌的关系看作一条边,连出来的是一个基环树森林. 对于一棵基环树,我们找出环, ...

  3. BZOJ 1040 (ZJOI 2008) 骑士

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

  4. 【BZOJ 1038】【ZJOI 2008】瞭望塔

    http://www.lydsy.com/JudgeOnline/problem.php?id=1038 半平面交裸题,求完半平面后在折线段上的每个点竖直向上和半平面上的每个点竖直向下求距离,统计最小 ...

  5. 【BZOJ 1036】【ZJOI 2008】树的统计 树链剖分模板题

    sth神犇的模板: //bzoj1036 题目:一个n个点的树每个点有一个权值,支持修改单点权值,求某两点路径上的点权和或最大点权. #include <cstdio> using nam ...

  6. [ZJOI 2008]泡泡堂BNB

    Description 题库链接 双方 \(n\) 人,给出每人的战斗力,赢一场加 \(2\) 分,平局 \(1\) 分,失败不得分.求最大和最小的得分. \(1\leq n\leq 100000\) ...

  7. 【BZOJ 1036】【ZJOI 2008】树的统计Count

    http://www.lydsy.com/JudgeOnline/problem.php?id=1036 复习了一下好写好调的lct模板啦啦啦--- #include<cstdio> #i ...

  8. 【ZJOI 2008】树的统计

    [题目链接] 点击打开链接 [算法] 树链剖分模板题 [代码] #include<bits/stdc++.h> using namespace std; #define MAXN 3000 ...

  9. 【ZJOI 2008】 生日聚会

    [题目链接] 点击打开链接 [算法] 动态规划 f[i][j][x][y]表示当前选了i个男生,j个女生,男生与女生差最大为x,女生与男生差最大为y的方案数 转移很显然,笔者不再赘述 [代码] #in ...

随机推荐

  1. idea修改变量及其引用

    idea 修改某一变量及其引用 选中变量 shift+f6(shift+fn+f6), ctrl+R的当前页面全局替换, ctrl+shift+R 项目中的全局替换

  2. T1077 多源最短路 codevs

    http://codevs.cn/problem/1077/ 时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题目描述 Description 已知n个点(n&l ...

  3. graphviz的使用

    安装:brew install graphviz 使用:dot -Tpng *.dot -o *.png 把dot文件转换为图片,* 换成具体的文件名, 这样你就成功的用脚本渲染出你要绘制的图片啦 参 ...

  4. 深入浅出:Linux设备驱动之字符设备驱动

    一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流 ...

  5. [Javascript] Wrap fireEvent with fireEventAsync

    The idea is wrap a object with all its function methods and add some additional handling into a new ...

  6. socket 网络编程高速入门(一)教你编写基于UDP/TCP的服务(client)通信

    由于UNIX和Win的socket大同小异,为了方便和大众化,这里先介绍Winsock编程. socket 网络编程的难点在入门的时候就是对基本函数的了解和使用,由于这些函数的结构往往比較复杂,參数大 ...

  7. Python正則表達式:怎样使用正則表達式

    正則表達式(简称RE)本质上能够看作一个小的.高度专业化的编程语言,在Python中能够通过re模块使用它.使用正則表達式,你须要为想要匹配的字符串集合指定一套规则,字符串集合能够包括英文句子.e-m ...

  8. 一道有关switch-case题目

    一道有关switch-case题目 /** * * @title:SwitchCase.java * @Package:com.you.hbxs.model * @Description:<h3 ...

  9. jquery easyui:EasyUI Treegrid 树形网格

    用jquery easyui 的 Treegrid 树形网格 进行数据展示,不过官网的API 和 demo 让我愣了好久,摸索后整理出来供大家详细参看. jquery easyui 官网:http:/ ...

  10. forEach、for-in与for-of的区别

    forEach.for-in与for-of的区别 forEach介绍 objArr.forEach(function (value) { console.log(value); }); foreach ...