1080. 骑士

题目链接

1080. 骑士

Z 国的骑士团是一个很有势力的组织,帮会中聚集了来自各地的精英。

他们劫富济贫,惩恶扬善,受到了社会各界的赞扬。

可是,最近发生了一件很可怕的事情:邪恶的 Y 国发起了一场针对 Z 国的侵略战争。

战火绵延五百里,在和平环境中安逸了数百年的 Z 国又怎能抵挡得住 Y 国的军队。

于是人们把所有希望都寄托在了骑士团身上,就像期待有一个真龙天子的降生,带领正义打败邪恶。

骑士团是肯定具备打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾。

每个骑士有且仅有一个他自己最厌恶的骑士(当然不是他自己),他是绝对不会与最厌恶的人一同出征的。

战火绵延,人们生灵涂炭,组织起一个骑士军团加入战斗刻不容缓!

国王交给你了一个艰巨的任务:从所有骑士中选出一个骑士军团,使得军团内没有矛盾的两人,即不存在一个骑士与他最痛恨的人一同被选入骑士军团的情况,并且使这支骑士军团最富有战斗力。

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

输入格式

输入第一行包含一个正整数 N,描述骑士团的人数;

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

输出格式

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

数据范围

N106,
每名骑士的战斗力都是不大于 106 的正整数。

输入样例:

3 10 2 20 3 30 1

输出样例:

30

解题思路

基环树dp

本题为树形dp 285. 没有上司的舞会 的基环树版本
删完基环上的任意一条边后即树形dp:f[x][0] 表示以 x 为根的子树不选 x 时的最大值,f[x][1] 表示以 x 为根的子树选 x 时的最大值
考虑环上的任意一条边:xy,对于 x 来说只有两种情况:选或不选,不选 x 时可以直接删除这条边,即对于跟 x 有关系的边的其他点可选可不选,这部分贡献为 f[x][0],选择 xy 不能选,进行树形dp 时特判一下即可,注意这时不用考虑删完这条边那些与 x 有关系的边,因为此时 x 必选,要求的是 f[x][1],转移时已经考虑到了

  • 时间复杂度:O(n)

代码

// Problem: 骑士 // Contest: AcWing // URL: https://www.acwing.com/problem/content/1082/ // Memory Limit: 64 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=1e6+6; int n; int h[N],e[N],ne[N],idx,w[N]; LL f1[N][2],f2[N][2],res; bool st[N],in[N],rm[N]; void add(int a,int b) { e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void dfs(int x,int u,LL f[][2]) { f[x][1]=-0x3f3f3f3f; if(x!=u)f[x][1]=w[x]; for(int i=h[x];~i;i=ne[i]) { if(rm[i])continue; int y=e[i]; dfs(y,u,f); f[x][0]+=max(f[y][0],f[y][1]); f[x][1]+=f[y][0]; } } void dfs_c(int x) { st[x]=in[x]=true; for(int i=h[x];~i;i=ne[i]) { int y=e[i]; if(!st[y])dfs_c(y); else if(in[y]) { rm[i]=true; dfs(y,-1,f1); dfs(y,x,f2); res+=max(f1[y][0],f2[y][1]); } } in[x]=false; } int main() { memset(h,-1,sizeof h); scanf("%d",&n); for(int i=1;i<=n;i++) { int a; scanf("%d%d",&w[i],&a); add(a,i); } for(int i=1;i<=n;i++) if(!st[i])dfs_c(i); printf("%lld",res); return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16789231.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示