首页 > 其他分享 >题解 AcWing 359.创世纪

题解 AcWing 359.创世纪

时间:2023-10-11 11:12:01浏览次数:35  
标签:last int 题解 不选 edge dp max 359 AcWing

题目描述

给你一个 \(n\) 个点 \(n\) 条边的有向图,若选了当前节点,那么当前节点的儿子节点至少有一个不能选。求最多能选多少个点。

具体思路

显然是一棵基环树,因此考虑基环树 dp。

我们先不管环的条件,先考虑朴素的树形 dp。


设 \(f_{x,0}\) 表示 \(x\) 节点不选,最多可以选多少个点,\(f_{x,1}\) 表示 \(x\) 节点选,最多可以选多少个点。

如果 \(x\) 不选的话,那么 \(x\) 的儿子 \(y\) 选或不选都没关系,有:

\[f_{x,0}=\max \limits_{y \in son(x)} \{ {f_{y,0},f_{y,1}} \} \]

如果 \(x\) 选的话,那么 \(x\) 的儿子里面就一定要有一个点不选,我们枚举这个不选的点,有:

\[f_{x,1}=\max \limits_{y \in son(x)} \{ {f_{y,0}+ \max \limits_{z \in son(x),z \ne y} \{ {f_{z,0},f_{z,1}} \}} \} \]

显然这个状态转移方程是 \(O(n^2)\) 的,考虑优化。

我们发现 \(\max \limits_{z \in son(x),z \ne y} \{ {f_{z,0},f_{z,1}} \}\) 和 \(f_{x,0}\) 的转移很像,因此考虑用 \(f_{x,0}\) 来表示 \(f_{x,1}\)。

有:

\[f_{x,1}=f_{x,0}+1+\max \limits_{y \in son(x)} \{ {f_{y,0}-\max(f_{y,0},f_{y,1})} \} \]

我们来理解一下这个式子。

首先,加一是因为你当前选了 \(x\) 这个点,因此贡献要加一。

其次,加上 \(f_{y,0}\) 是因为你 \(y\) 这个点不选,因此要加上它不选的贡献。

然后,我们发现 \(f_{x,0}\) 里面计算了一遍 \(y\) 的贡献,因此我们要将它减去。

最后,我们设的 \(f_{x,1}\) 表示的是最多可以放多少个点,因此要对每个 \(y\) 都取一遍最大值。


现在问题就转换成了如果树上有环,应该如何计算这个环对动态规划的影响。

image

如图所示,\(x\) 和 \(y\) 分别是环的两个端点,考虑断边 \(edge(x,y)\)。

  • 若 \(edge(x,y)\) 没有影响

    1. 若 \(x\) 不选,那么 \(y\) 选不选都没关系。

    2. 若 \(x\) 选,但 \(x\) 有除 \(y\) 以外的儿子,那么我们把 \(edge(x,y)\) 断了,那么我们 dp 的时候枚举不选的点就是 \(x\) 的其他儿子,那么此时 \(y\) 选不选都没关系。

  • 若 \(edge(x,y)\) 有影响

    1. 显然只有一种情况,\(x\) 选,并且 \(y\) 强制不选,那么此时我们的 dp 就要略加修改。

因为我们强制 \(y\) 不选,因此在 dp 的时候我们不用在枚举哪个点不选了,有:

\[f_{x,1}=f_{x,0}+1 \]

Code

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
const int inf=0x3f3f3f3f;
struct edge{int x,y,pre;}a[N];
int last[N],alen;
void ins(int x,int y){
	a[++alen]=edge{x,y,last[x]};
	last[x]=alen;
}
int fa[N],f[N][2],v[N],rt,bk;
void treedp(int x){
	f[x][0]=f[x][1]=0,v[x]=1;
	int res=-inf;
	for(int k=last[x];k;k=a[k].pre){
		int y=a[k].y;
		if(y==rt)continue;
		treedp(y);
		f[x][0]+=max(f[y][0],f[y][1]);
		res=max(res,f[y][0]-max(f[y][0],f[y][1]));
	}
	f[x][1]=f[x][0]+res+1;
	if(x==fa[rt]&&bk){
		f[x][1]=f[x][0]+1;
	}
}
int main(){
	int n;scanf("%d",&n);
	alen=1;memset(last,0,sizeof(last));
	for(int i=1;i<=n;i++){
		scanf("%d",&fa[i]);
		ins(fa[i],i);
	}
	int ans=0;
	for(int i=1;i<=n;i++){
		if(v[i])continue;
		rt=i;
		while(!v[fa[rt]]){
			v[rt]=1;
			rt=fa[rt];
		}
		bk=0;treedp(rt);
		int res=max(f[rt][0],f[rt][1]);
		bk=1;treedp(rt);
		res=max(res,f[rt][0]);
		ans+=res;
	}
	printf("%d",ans);
	return 0;
}

标签:last,int,题解,不选,edge,dp,max,359,AcWing
From: https://www.cnblogs.com/reclusive2007/p/17756561.html

相关文章

  • 网络规划设计师真题解析--位示图大小计算
    假设某计算机的字长为32位,该计算机文件管理系统磁盘空间管理采用位示图,记录磁盘的使用情况,若磁盘的容量为300GB,物理块的大小为4MB,那么位示图的大小为(2)个字。(2020年)(2)A.2400 B.3200 C.6400 D.9600答案:A解析:已知磁盘容量为300GB,物理块大小为4MB则计算物理块数=300*1024/4=76800(个)位......
  • 题解: CF768D Jon and Orbs
    题解:CF768DJonandOrbs一句话体面:有k种不同的物品,每天等概率任取一种(不一定是新的种类)。q组询问,每组给出一个p,问取完这k件物品的概率不小于\(\frac{p}{2000}\)的最小天数不用说,肯定是概率DP了1.定义:\(f_{i,j}\)表示前\(i\)天选取了\(j\)种物品的概率(\(P.S.\)该定义不......
  • 题解 DIFERENC - DIFERENCIJA
    题目描述给出一个长度为\(n\)的序列\(a_i\),求出下列式子的值:\[\sum_{i=1}^n\sum_{j=i}^n(\max\limits_{i\lek\lej}a_k-\min\limits_{i\lek\lej}a_k)\]即定义一个子序列的权值为序列内最大值与最小值的差。求出所有连续子序列的权值和。具体思路暴力思路很好......
  • p4801题解
    解题思路:确实是一道很好的贪心,但由于加上了水这个影响因素,使题目复杂度上升了不少。(考虑的东西多了嘛)输个入。对饼干温度无脑排序。求最小值。求最大值(用双指针做,后面会讲)。解题过程:先输入(这个步骤就不用我讲了)inta[1000005];longlongn,ws;longlongmin......
  • 洛谷P4158 [SCOI2009] 粉刷匠 题解
    所有的\(DP\),只要式子一推出来(不管复杂度),那就很简单了,因为优化是成千上万种的……思路1:我们考虑设\(f[i][j][k]\)表示:当前\(DP\)到第\(i\)块木板的第\(j\)个位置,共涂了\(k\)次,所能获得的最大收益。因为还要枚举当前这次涂是从哪到哪的,因此复杂度为\(O(NM^2T)\),实......
  • 洛谷P3300 [SDOI2013] 城市规划 题解
    [SDOI2013]城市规划题意:给你一个\(6\timesn\)的网格题,单点修改,询问区间联通块数,\(n\le10^5\)。解:看起来就很显然的一道题......线段树每个点用一个ufs维护连通性;我为了方便思考把图转成横着的了。写起来真是毒瘤......重点在于:\(\bullet\)1、建立叶节点。\(\bull......
  • 【ABC320C】题解
    AtCoderBeginnerContest320ProblemC-SlotStrategy2(Easy)题解题目简述给定\(3\)个长度为\(m\)的转盘,转动过后三个转盘分别可以在不同的时间停下,求停下时所有转盘都显示相同数字的最小时间。思路由于这题\(m\le100\),数据较水,所以可以先把每个数列都复制\(......
  • 【ABC320D】题解
    AtCoderBeginnerContest320ProblemD-RelativePosition题解题目保证不矛盾,就可以直接vector建图,然后dfs一遍,边权为\((w_x,w_y)\)表示坐标的差,从\(u=1\)开始搜索,设点\(u,v\)有一条无向边,\(v_x=u_x+w_x,v_y=u_y+w_y\),最后如果没有被标记过的话(也就是没有......
  • 【题解】Fibonacci-ish II
    传送门题目分析根据题目范围\(n\le30000\)并且此题可以离线维护这个很恶心的东西,所以我们考虑莫队。由于要求访问到任意一个区间都要求知道它有序之后的序列,所以这个东西可以用权值线段树维护。因此,此题正解是莫队+权值线段树。我们分类讨论一下加上一个数,删除一个数对答案......
  • 题解 P3894【[GDOI2014] 传送】
    难倒不难,128MB的空间限制快恶心死我了。我们设\(d_{u_0,u_1}\)表示到节点\((u_0,u_1)\)距离最近的叶子的距离,这个可以很容易换根DP求出。设\(p_{u_0}\)表示树\(u_0\)中距离最近的两个叶子的距离。设\(dis(u_0,u_1,v_0,v_1)\)(\(u_0=v_0\))表示树中两个节点\(u_1\)和......