基环内向树上 dp,不过在这里提供给一种非典型做法。

考虑将环上的每一条边都断开,这样就会形成多棵树,先在这些树上进行树形 \(dp\)。设 \(dp_{i,0/1}\) 表示不选/选 \(i\) 时,\(i\) 子树内的最大选点数。明显方程为:

\[\begin{cases}dp_{u,0}=\sum\limits_{v\in uson}\max(dp_{v,0},dp_{v,1})\\ \\dp_{u,1}=[\sum\limits_{v\in uson}[dp_{v,0}\ge dp_{v,1}]>0]?dp_{u,0}:dp_{u,0}-\min\limits_{v\in uson}(dp_{v,1}-dp_{v,0})\end{cases}
\]

接下来,我们开始在环上找答案。考虑断环为链。设 \(f_{i,0/1,0/1}\) 表示在环上的第 \(i\) 个点,选不选,第 \(cnt\) 个点选不选,\(lp_i\) 表示环上第 \(i\) 个点的编号。则转移方程为:

\[\begin{cases}
f_{i,0,0/1}=\max(f_{i-1,0,0/1},f_{i-1,1,0/1})+dp_{lp_i,0}\\
f_{i,1,0/1}=\max(f_{i-1,0,0/1}+dp_{lp_i,0}+1,f_{i-1,1,0/1}+dp_{lp_i,1})
\end{cases}
\]

时间复杂度瓶颈为并查集(不知道并查集干什么用的,详见上一道题我写的题解),时间复杂度 \(O(n\log n)\)。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+5;
int n,m,h[N],to[N],nxt[N];
int cnt,lp[N],v[N],fh[N],ans;
int dp[N][2],f[N][2][2],t[N];
void add(int x,int y){
to[++m]=y;
nxt[m]=h[x];
h[x]=m;
}void init(){
for(int i=1;i<=n;i++)
fh[i]=i;
}int find
(int x){
if(fh[x]==x) return x;
return fh[x]=find(fh[x]);
}void unite(int x,int y){
x=find(x);
y=find(y);
if(x==y) return;
fh[y]=x;
}void dp_(int x){
int f=1,mn=1e9;
for(int i=h[x];i;i=nxt[i]){
if(v[to[i]]) continue;
int y=to[i];dp_(y);
dp[x][0]+=max(dp[y][0],dp[y][1]);
if(dp[y][0]>=dp[y][1]) f=0;
else mn=min(mn,dp[y][1]-dp[y][0]);
}dp[x][1]=dp[x][0]+1;
if(f) dp[x][1]-=mn;
}void solve(int rt){
int x=rt,y=t[rt];cnt=0;
lp[++cnt]=y;v[y]=1;
while(y!=x){
lp[++cnt]=t[y];
v[t[y]]=1;y=t[y];
}for(int i=1;i<=cnt;i++) dp_(lp[i]);
f[0][0][1]=f[0][1][0]=-1e9;
for(int i=1;i<=cnt;i++){
f[i][0][0]=max(f[i-1][0][0],f[i-1][1][0])+dp[lp[i]][0];
f[i][1][0]=max(f[i-1][0][0]+dp[lp[i]][0]+1,f[i-1][1][0]+dp[lp[i]][1]);
f[i][0][1]=max(f[i-1][0][1],f[i-1][1][1])+dp[lp[i]][0];
f[i][1][1]=max(f[i-1][0][1]+dp[lp[i]][0]+1,f[i-1][1][1]+dp[lp[i]][1]);
}ans+=max(f[cnt][0][0],f[cnt][1][1]);
}int main(){
scanf("%d",&n);init();
for(int i=1;i<=n;i++){
cin>>t[i];
add(t[i],i);
unite(t[i],i);
}for(int i=1;i<=n;i++)
if(find(i)==i) solve(i);
printf("%d",ans);
return 0;
}//Kaká

[BZOJ3037] 创世纪 题解的更多相关文章

  1. bzoj3037 创世纪

    两种解法: 一.树状DP /*by SilverN*/ #include<iostream> #include<algorithm> #include<cstring&g ...

  2. BZOJ3037 创世纪[基环树DP]

    实际上基环树DP的名字是假的.. 这个限制关系可以看成每个点有一条出边,所以就是一个内向基环树森林. 找出每个基环树的环,然后对于树的部分,做DP,设状态选或不选为$f_{x,0/1}$,则 $f_{ ...

  3. BZOJ3037 创世纪(基环树DP)

    基环树DP,攻的当受的儿子,f表选,g表不选.并查集维护攻受关系.若有环则记录,DP受的后把它当祖宗,再DP攻的. #include <cstdio> #include <iostr ...

  4. 【BZOJ3037/2068】创世纪/[Poi2004]SZP 树形DP

    [BZOJ3037]创世纪 Description applepi手里有一本书<创世纪>,里面记录了这样一个故事……上帝手中有着N 种被称作“世界元素”的东西,现在他要把它们中的一部分投放 ...

  5. [bzoj3037/2068]创世纪[Poi2004]SZP_树形dp_并查集_基环树

    创世纪 SZP bzoj-3037/2068 Poi-2004 题目大意:给你n个物品,每个物品可以且仅可以控制一个物品.问:选取一些物品,使得对于任意的一个被选取的物品来讲,都存在一个没有被选取的物 ...

  6. Poetize4 创世纪

    3037: 创世纪 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 123  Solved: 66[Submit][Status] Description ...

  7. CH6401 创世纪

    6401 创世纪 0x60「图论」例题 描述 上帝手中有 N(N≤10^6) 种世界元素,每种元素可以限制另外1种元素,把第 i 种世界元素能够限制的那种世界元素记为 A[i].现在,上帝要把它们中的 ...

  8. JZOJ 3929. 【NOIP2014模拟11.6】创世纪

    3929. [NOIP2014模拟11.6]创世纪 (Standard IO) Time Limits: 1000 ms Memory Limits: 65536 KB Description 上帝手 ...

  9. T1创世纪(原创)

    创世纪 这是我的第一道原创题 题解: 这道题的核心算法是:加维度的最短路+贪心 状态:\(dis[i][j][t][a]\)表示在 \(t\) 时,到达 \((i,j)\) ,当前共造\(a\)只&q ...

  10. 为创世纪图书馆(Library Genesis)作镜像

    简介 Library Genesis的Wikipedia条目中的介绍是: Library Genesis or LibGen is a search engine for articles and b ...

随机推荐

  1. 雪碧图的魔力:优化CSS动画场景

    什么是雪碧图 雪碧图(CSS Sprites),是一种网页图像处理技术,它将多个小图标或图像合并成一个大的图像文件.这种方法允许浏览器通过一次HTTP请求加载多个图像,而不是为每个小图标单独发起请求. ...

  2. 如何在 Epicor 中计算绩效

    制造性能是任何生产工序的关键,允许企业衡量和评估其效率和生产力水平. 我们将探讨如何在 Epicor 中计算制造性能.计算整体设备效率(OEE) 时性能指标的价值.如何解释制造指标以及在 Epicor ...

  3. uni-app小程序项目使用iconfont字体图标

    前情 uni-app是我比较喜欢的跨平台框架,它能开发小程序/H5/APP(安卓/iOS),重要的是对前端开发友好,自带的IDE让开发体验非常棒,公司项目就是主推uni-app. 为什么要这么做? 借 ...

  4. Fuzz技术综述与文件Fuzz

    文章一开始发表在微信公众号 https://mp.weixin.qq.com/s?__biz=MzUyNzc4Mzk3MQ==&mid=2247486189&idx=1&sn= ...

  5. Python绘制七段数码管字母:从理论到实践

    在现代电子显示技术中,七段数码管是一种广泛应用的显示器件,常用于显示数字.字母和一些特殊符号.其基本原理是通过控制七个发光段(a, b, c, d, e, f, g)的亮灭来形成不同的显示内容.本文将 ...

  6. Qt/C++音视频开发61-多屏渲染/一个解码渲染到多个窗口/画面实时同步

    一.前言 多屏渲染就是一个解码线程对应多个渲染界面,通过addrender这种方式添加多个绘制窗体,我们经常可以在展会或者卖电视机的地方可以看到很多电视播放的同一个画面,原理应该类似,一个地方负责打开 ...

  7. .NET Bioss相关数据读写

    本文我们介绍针对Bios如何读取.写入数据,比如最常见的SN读取以及烧录 WMI查询 先看看WMI方式,可以用于查询和管理Windows系统的各种信息,包括读取BIOS信息 WMI-Win32_BIO ...

  8. IM开发干货分享:我是如何解决大量离线消息导致客户端卡顿的

    1.引言 好久没写技术文章了,今天这篇不是原理性文章,而是为大家分享一下由笔者主导开发实施的IM即时通讯聊天系统,针对大量离线消息(包括消息漫游)导致的用户体验问题的升级改造全过程. 文章中,我将从如 ...

  9. 即时通讯技术文集(第20期):IM架构设计技术文章(Part3) [共14篇]

    为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第20 期. [-1-] 融云技术分享:全面揭秘亿级IM消息的可靠投递机制 [链接] http: ...

  10. 学Shiro完结版-2

    第四章 INI配置--<跟我学Shiro> 之前章节我们已经接触过一些INI配置规则了,如果大家使用过如Spring之类的IoC/DI容器的话,Shiro提供的INI配置也是非常类似的,即 ...