BZOJ 3037 创世纪 树形DP

题目大意:给定一张有向图,每个点有且仅有一条出边,要求若一个点x扔下去,至少存在一个保留的点y,y的出边指向x,求最多扔下去多少个点

首先原题的意思就是支配关系 我们反向考虑 求最少保留的点 要求一个点若扔出去 则必须存在一个保留的点指向它

于是这就是最小支配集 不过由于是有向图 所以一个点要么选择 要么被子节点支配 所以就只剩下2个状态了

设f[x]为以x为根的子树选择x的最小支配集 g[x]为不选择x的最小支配集

然后由于是基环树林 所以我们选择一个环上的点 拆掉它的出边 设这个点为x 出边指向的点为y 讨论

1.若x选择 则y一开始就是被支配状态 g[y]初值为0 求一遍最小支配集

2.若x不选 正常求最小支配集即可

两种情况取最小值计入ans 最后输出n-ans即可

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 1001001
#define INF 0x3f3f3f3f
using namespace std;
struct abcd{
	int to,next;
	bool ban;
}table[M];
int head[M],tot;
int n,p,conquered,ans,a[M],f[M],g[M],fa[M];//f 选 g 被支配
bool v[M];
void Add(int x,int y)
{
	table[++tot].to=y;
	table[tot].next=head[x];
	head[x]=tot;
}
void DFS(int x)
{
	v[x]=1;
	if(v[a[x]])
		p=x;
	else
		DFS(a[x]);
}
void Tree_DP(int x)
{
	int i;
	f[x]=1;
	g[x]=INF;
	v[x]=1;
	if(x==conquered)
		g[x]=0;
	for(i=head[x];i;i=table[i].next)
		if(!table[i].ban&&table[i].to!=fa[x])
		{
			fa[table[i].to]=x;
			Tree_DP(table[i].to);
			g[x]+=min(f[table[i].to],g[table[i].to]);
			g[x]=min(g[x],f[x]+f[table[i].to]-1);
			f[x]+=min(f[table[i].to],g[table[i].to]);
		}
}
int main()
{
	int i;
	cin>>n;
	for(i=1;i<=n;i++)
		scanf("%d",&a[i]),Add(a[i],i);
	for(i=1;i<=n;i++)
		if(!v[i])
		{
			DFS(i);
			table[p].ban=1;
			conquered=a[p];
			Tree_DP(p);
			int temp=f[p];
			conquered=0;
			Tree_DP(p);
			temp=min(temp,g[p]);
			ans+=temp;
		}
	cout<<n-ans<<endl;
}
时间: 2024-08-05 01:09:04

BZOJ 3037 创世纪 树形DP的相关文章

BZOJ 3037 创世纪

题解: 首先从基环树上的环上选两个点x,y 断开x,y之间的边,然后做树形DP. 设f[x]为选x的情况下的最大值,g[x]为不选x的情况下的最大值. 分两种情况讨论, 1.选x,则y一开始就处于被支配状态,在计算y的f[]函数值时需要特判. 2.不选x,按正常DP做即可. 1 #include<cstdio> 2 #include<vector> 3 using namespace std; 4 #define ll long long 5 #define FILE "

BZOJ 4033 HAOI2015 T1 树形DP

题目大意:给定一棵树,你需要把其中的k个点染成黑色,使得黑色点两两之间的距离和+白色点两两之间的距离和最大,求最大值 题解戳这里 Orz ydcydc 看来我对于非线性的树形DP还是做得太少了QwQ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 2020 using namespace std; struct edge{ int

BZOJ 1017--魔兽地图(树形DP&amp;完全背包)

1017: [JSOI2008]魔兽地图DotR Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 2674  Solved: 1041[Submit][Status][Discuss] Description DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Ancients) Allstars.DotR里面的英雄只有一个属性——

BZOJ 1596--电话网络(树形DP)

1596: [Usaco2008 Jan]电话网络 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1139  Solved: 534[Submit][Status][Discuss] Description Farmer John决定为他的所有奶牛都配备手机,以此鼓励她们互相交流.不过,为此FJ必须在奶牛们居住的N(1 <= N <= 10,000)块草地中选一些建上无线电通讯塔,来保证任意两块草地间都存在手机信号.所有的N块草地按1..N 顺

BZOJ 1040: [ZJOI2008]骑士( 树形dp )

这是一个森林中, 每棵树上都有一个环...每棵树单独处理, 找出环上任意一条边断开, 限制一下这条边两端点的情况, 然后就可以树dp了.. ------------------------------------------------------------------------ #include<cstdio> #include<algorithm> #include<cstring> #include<cctype> using namespace

BZOJ 3829 Poi2014 FarmCraft 树形DP+贪心

题目大意:给定一棵树,从1号节点出发对树进行欧拉遍历,每到达一个点这个点就开始装MC,每个点装MC的时间不同,最后回到1号节点装MC,求所有人都能联机的最少时间 令f[x]为对第x个节点进行欧拉遍历的时间,g[x]为对第x个节点进行欧拉遍历并完成所有节点的装机的最小时间 那么在每个节点以什么顺序遍历每棵子树呢? 我们发现装机多出来的时间 即g[x]-f[x]可以用来遍历其它子树 那么显然要从g[x]-f[x]大的子树开始遍历 因此对每个节点的子树按照g[x]-f[x]递减排个序即可 时间复杂度O

BZOJ 1131 POI2008 Sta 树形DP

题目大意:给定一个n个点的无根树,要求找到一个根节点,使深度之和最大 令f[x]为以x为根的子树的深度之和 首先我们找到任意一个节点进行深搜,统计出每棵子树的大小,以及所有点的深度之和 然后再以该节点为根深搜一遍,此时状态从父节点转移至子节点,转移方程如下: 当我们将根节点从4节点变为5节点时,橙色部分每个点的深度+1,绿色部分每个点的深度-1 故得到状态转移方程: f[x]=f[fa[x]]+n-2*size[x] 最后扫一遍数组即可出解 #include<cstdio> #include&

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

创世纪 SZP bzoj-3037/2068 Poi-2004 题目大意:给你n个物品,每个物品可以且仅可以控制一个物品.问:选取一些物品,使得对于任意的一个被选取的物品来讲,都存在一个没有被选取的物品,而且选取的个数最大. 注释:$1\le n \le 10^6$. 想法:显然,和骑士类似的,是一个基环树森林.如果A物品可以控制B物品,那就有B物品向A物品连边.对于每一个基环树,如果这个基环树是树的话显然变成树形dp入门题,暴力树形dp即可.然后对于基环树来讲,我们依然记录环上两点,分别以这两

BZOJ 1093 最大半连通子图(强连通分量+树形DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1093 题意: 思路:(1)首先,强连通分量中的一个点若在最大半连通子图中,则必定整个连通分量中的点都在,因为都在还是满足半连通的性质而且使得节点数更多. (2)因此,求出强连通分量缩点,形成一个有向无环图,其实与树是差不多的.在这个图上DP一次即可,也就是找出最长链以及最长链的个数. vector<int> g[N],g1[N]; int n,m,mod; int dfn[N],lo