CF1877 E. Autosynthesis 基环树dp

传送门:CF

[前题提要]:一道基环树dp,但是题目有点绕,当时卡了我整整半天,到了第二天换了和清醒的脑子然后和别人讨论才整明白,故记录一下

题目很绕,故不再介绍.

首先对于这种下标和值有关系的题目.其实不难想到建图(CF上有大量这种 t r i c k trick trick),随便举个类似的题目:CF1768D.所以我们考虑每一个位置下标连向值建图.(注意我们建出来的图中的所有点都是点下标之前的关系)

首先,按照套路,每一个点都有且只有一条出边,也就是每一个点的出度都为1,那么这张图其实是一棵内向基环树.

然后想一下这样建图有什么意义.我们发现我们圈出一个点,其实多出来的是这个点的下标的贡献,那么我们想要选出这个点,按照题意,我们得需要一个值为我们选出来的点的下标的点留下来.那么这个点在哪里呢.就是我们选出来的这个点的入点.(请仔细理解这一部分).

所以我们想要选出一个点,必须得存在一个入点留下来.

然后我们考虑一个点想要留下来.要满足什么条件.我们一个点留下来了,多出来的是这个点的值的贡献,所以我们得需要一个下标为这个值的点被选出来.这个点在哪里呢,这个点显然就是我们当前点的出点.(因为我们每一个点都指向下标为该点值的点).


总结一下就是:
一个点想要留下来,它的父亲必须删除.一个点想要删除,必须存在一个儿子留下来

然后根据上述结论,其实我们不难发现,叶子节点都是得保留下来的,因为没有一个点指向叶子节点,也就是,没有一个点的值等于我们的叶子结点的下标

所以我们考虑对这棵基环树进行拓扑(其实这也是基环树dp的经典套路,拓扑排序).从叶子节点开始倒推,一步一步的确定每一个点的状态(此时我们会发现一个点的状态其实是一定的,因为有一个点只要有儿子留下来,该点就必须删除,没有儿子留下来的时候,该点又只能留下来).所以我们可以使用树形 d p dp dp来推出每一个根节点的状态(保留或者删除).

这里补一下上述做法:因为该图是一个基环树,按照经典做法,我们考虑求出环上的每一个点,那么对于每一个点来说,他都是一棵树的根节点(基环树的性质).所以我们可以对每一个根节点形成的树进行树形 d p dp dp.然后求出每一个根节点的状态最后进行环形 d p dp dp.

所以我们现在是求出了环上每一个点的状态.所以我们考虑环上该怎么办.
详细讨论一下就会发现存在以下几种情况:

  1. 环上的每一个点独立状态都是保留.此时需要注意的是,我们环上的点其实相互都是有入点和出点的.所以此时的保留状态其实是可以变为删除状态的.此时我们只要随便选一个点保留,然后对应的出点需要删除.显然的,我们会发现只要是奇数点必然会出现矛盾,是偶数环则不会.
  2. 环上存在一个点是删除状态的.我们考虑从这个删除状态出发.因为环上一个点如果删除了.它的出点就不会有这个点的贡献.所以出点如果是删除状态,那么还是删除状态;如果是保留状态,那么需要变为删除状态,然后使用之前的性质递推下去.这里需要注意的是,我们需要从删除状态出发.

举个栗子:

在这里插入图片描述

0代表独立状态为删除,1代表保留.如果我们从下面那个3出发,我们会发现4变为0,3也变为0.但是当3变为0的时候,4不能变为0.所以此时出现了问题.
但是为什么从0出发就没有问题呢.因为从0出发,我们最后循环到自己这个位置的时候因为他是0,所以无论后面是1还是0,他都可以是0(不会对初始状态产生影响).所以我们会发现这样构造一定是成立的.

还有一点需要注意的是,本题可能是一个基环树森林


下面是具体的代码部分:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define root 1,n,1
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {ll x=0,w=1;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';return x*w;
}
inline void print(__int128 x){if(x<0) {putchar('-');x=-x;}if(x>9) print(x/10);putchar(x%10+'0');
}
#define maxn 1000000
#define int long long
const int mod=998244353;
const double eps=1e-8;
#define	int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3f
int a[maxn];vector<int>edge[maxn];
int in[maxn];int n;int vis[maxn],mp[maxn];int cnt=0;
void dfs(int u,int per_u) {//找环for(auto v:edge[u]) {if(v==per_u) continue;if(in[v]==1||vis[v]==1) continue;mp[++cnt]=v;vis[v]=1;dfs(v,u);}
}
int state[maxn];//1保留,0删除
void solve(int u,int per_u) {//树形dpif(edge[u].size()==1) {state[u]=1;return ;}int this_cnt=0;for(auto v:edge[u]) {if(v==per_u) continue;if(in[v]==2) continue;solve(v,u);this_cnt+=state[v];}if(this_cnt!=0) state[u]=0;else state[u]=1;
}
void init() {for(int i=1;i<=cnt;i++) {mp[i]=0;}
}
int flag=0;
void topo() {queue<int>q;for(int i=1;i<=n;i++) {if(in[i]==1) {q.push(i);}}while(!q.empty()) {int u=q.front();q.pop();for(auto v:edge[u]) {in[v]--;if(in[v]==1) {q.push(v);}}}for(int i=1;i<=n;i++) {if(in[i]==2&&vis[i]==0) {cnt=0;mp[++cnt]=i;vis[i]=1;dfs(i,0);for(int j=1;j<=cnt;j++) {solve(mp[j],0);}int pos=0;int this_cnt=0;for(int j=1;j<=cnt;j++) {this_cnt+=state[mp[j]];if(state[mp[j]]==0) {pos=j;}}if(this_cnt==cnt) {//全是1,说明可以乱填,但如果是奇数,不行if(cnt&1) {flag=1;break;}else {int num=1;for(int j=1;j<=cnt;j++) {state[mp[j]]=num;num^=1;}}}else {//如果不是,那么如果一个点没有儿子,那这个1不能变成0//反之可以变为0(因为环中也可以保留点),所以应该从0出发for(int j=pos;j<=pos+cnt-1;j++) {if(state[mp[(j-1+cnt)%cnt+1]]==1) {if(state[mp[(j+cnt)%cnt+1]]) {state[mp[(j+cnt)%cnt+1]]=0;}}}}if(flag) break;init();}}if(flag) {cout<<-1<<endl;}else {int this_cnt=0;for(int i=1;i<=n;i++) {if(state[i]==1) {this_cnt++;}}cout<<this_cnt<<endl;for(int i=1;i<=n;i++) {if(state[i]==1) {cout<<a[i]<<" ";}}cout<<endl;}
}
signed main() {
//	freopen("input.in","r",stdin);
//	freopen("output.out","w",stdout);n=read();for(int i=1;i<=n;i++) {a[i]=read();edge[i].push_back(a[i]);edge[a[i]].push_back(i);in[i]++;in[a[i]]++;}topo();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/189415.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

12月1日作业

代码整理&#xff0c;将学过的三种运算符重载&#xff0c;每个至少实现一个运算符的重载 #include <iostream>using namespace std;class Cloudy {friend bool operator!(const Cloudy &L,const Cloudy &R); private:int a; public:int b; public:Cloudy(){}Clo…

【Java】浅析FutureTask的核心方法get

前言 在进行多线程编程时&#xff0c;我们离不开两个重要的任务接口&#xff1a;Runnable、Callable。一个线程想要运行&#xff0c;首先它得知道它的任务是什么&#xff08;它要做什么&#xff09;&#xff0c;而这两个接口恰好是用于表示一个线程需要执行的任务。 Runnable和…

SHAP(三):在解释预测模型以寻求因果见解时要小心

SHAP&#xff08;三&#xff09;&#xff1a;在解释预测模型以寻求因果见解时要小心 与 Microsoft 的 Eleanor Dillon、Jacob LaRiviere、Scott Lundberg、Jonathan Roth 和 Vasilis Syrgkanis 合作撰写的关于因果关系和可解释机器学习的文章。 当与 SHAP 等可解释性工具配合…

Mac 安装 Django 并连接 MySQL

一、下载安装运行Django看官方教程就好了&#xff0c;网址&#xff1a;Django 安装_w3cschool 二、连接MySQL&#xff08;我用的是pymysql和mysqlclient&#xff09;&#xff1a; 1、创建好项目后找到这个文件 2、修改当中的连接信息&#xff0c;将这些信息改成你自己的就好了…

2023-12-01 AIGC-自动生成ppt的AI工具

摘要: 2023-12-01 AIGC-自动生成ppt-记录 自动生成ppt: BoardMix boardmix 一键生成ppt boardmix是一款基于云的ai设计软件&#xff0c;允许创建用于各种目的的自定义演示文稿、ai绘画&#xff0c;ai生成思维导图等。以下是它的一些功能&#xff1a; 可定制的模板 - 它有一个…

Redis基本命令

文章目录 第1关&#xff1a;字符串、列表与集合第2关&#xff1a;哈希与有序集合第3关&#xff1a;Redis基本事务与其他命令 第1关&#xff1a;字符串、列表与集合 编程要求 根据提示&#xff0c;在右侧Begin-End区域补充代码&#xff0c;完成任务分配的后端处理逻辑&#xff…

Python-docx 深入word源码 自定义页码页脚以动态显示总页数和当前页数

代码和效果图 先上能够正常显示页码页脚的Python代码和效果图&#xff0c;之后再解释原理和思路 from docx import Document from docx.shared import Pt from docx.oxml import OxmlElement from docx.enum.text import WD_PARAGRAPH_ALIGNMENT from docx.oxml.ns import qn…

Elasticsearch:什么是非结构化数据?

非结构化数据定义 非结构化数据是指未按照设计的模型或结构组织的数据。 非结构化数据通常被归类为定性数据&#xff0c;可以是人类或机器生成的。 非结构化数据是最丰富的可用数据类型&#xff0c;经过分析后&#xff0c;可用于指导业务决策并在许多其他用例中实现业务目标。…

java原子类型

AtomicBoolean AtomicInteger AtomicLong AtomicReference<V> StringBuilder - 不是原子类型。StringBuilder 是 java.lang 包下的类 用法&#xff1a;无需回调改变数值

【学习记录】从0开始的Linux学习之旅——应用开发(helloworld)

一、概述 Linux操作系统通常是基于Linux内核&#xff0c;并结合GNU项目中的工具和应用程序而成。Linux操作系统支持多用户、多任务和多线程&#xff0c;具有强大的网络功能和良好的兼容性。本文主要讲述如何在linux系统上进行应用开发。 二、概念及原理 应用程序通过系统调用与…

今日现货黄金最新建议

近期现货黄金价格再度逼近历史高位&#xff0c;很多本来在场外观望的投资者&#xff0c;都纷纷希望进场一试身手。然而大涨大跌的行情并不是很适合新手投资者参与&#xff0c;如果大家还没做好技术上的准备&#xff0c;可以多听听正规交易平台的专业人士的意见。 在正式入市之前…

【LeetCode每日一题合集】2023.11.20-2023.11.26 (二叉树中的伪回文路径)

文章目录 53. 最大子数组和解法1——DP解法2——分治&#xff08;维护区间、类似线段树的思想&#xff09; 2216. 美化数组的最少删除数&#xff08;贪心&#xff09;2304. 网格中的最小路径代价1410. HTML 实体解析器&#xff08;模拟&#xff09;2824. 统计和小于目标的下标对…

jsp前端输入中文数据传到controller变成问号?的解决办法

还是写老师布置的实验的时候&#xff0c;解决了xml文件找不到的问题之后又遇到新的问题&#xff1a;前端登录处输入用户名和密码&#xff0c;结果明明输入的用户名是对的密码也是对的&#xff08;输入的用户名是中文&#xff09;&#xff0c;它就是显示用户名或密码错误。然后我…

mac 系统 vmware 安装centos8

选择镜像 安装系统 依次设置有告警的项目 设置用户名密码 设置root密码 重启系统 重启成功进入下面界面 勾选&#xff0c;点击done 点击箭头所指按钮 输入密码登录 安装成功了 设置网络 打开终端 切换root用户 输入下面指令 su root 输入root的密码 安装git

【Cisco Packet Tracer】交换机 学习/更新/泛洪/VLAN实验

交换机的功能是连接计算机、服务器、网络打印机、网络摄像头、IP电话等终端设备&#xff0c;并实现与其它交换机、无线接入点、路由器、网络防火墙等网络设备的互联&#xff0c;从而构建局域网络&#xff0c;实现所有设备之间的通信。 本文使用Cisco Packet Tracer仿真软件&…

DynamicDataSource

DynamicDataSource 多数据源&#xff0c;读写分离&#xff0c;主从数据库

算法题--排椅子(贪心)

题目链接 code #include<bits/stdc.h> using namespace std;struct node{int indx;//用来存储数组下标int cnt;//用来计数 };bool cmp(node a,node b){ //判断是否是数字最大的一个就是经过最多谈话人的道return a.cnt>b.cnt; } node row[2010],cow[2010];bool cmp…

润和软件HopeStage与深信服终端安全管理系统完成产品兼容性互认证

近日&#xff0c;江苏润和软件股份有限公司&#xff08;以下简称“润和软件”&#xff09;HopeStage 操作系统与深信服科技股份有限公司&#xff08;以下简称“深信服”&#xff09;终端安全管理系统完成产品兼容性测试。 测试结果表明&#xff0c;企业级通用操作系统HopeStage…

Elasticsearch 优化查询中获取字段内容的方式,性能提升5倍!

1、背景 集群配置为&#xff1a;8 个 node 节点&#xff0c;16 核 32G&#xff0c;索引 4 分片 1 副本。应用程序的查询逻辑是按经纬度排序后找前 200 条文档。 1、应用对查询要求比较高&#xff0c;search 没有慢查询的状态。 2、集群压测性能不能上去&#xff0c;cpu 使用未打…

【已解决】如何打开设置了密码的7Z压缩文件?

7Z是一种常见的压缩文件格式&#xff0c;相比RAR和ZIP格式&#xff0c;它的压缩率更高&#xff0c;可以压缩出更小的文件体积&#xff0c;也同样可以设置密码保护&#xff0c;那设置了密码的7Z压缩文件要如何打开呢&#xff1f; 我们知道&#xff0c;7Z压缩文件设置密码保护后…