bzoj4316小C的独立集(dfs树/仙人掌+DP)
本题有两种写法,dfs树上DP和仙人掌DP。
先考虑dfs树DP。
什么是dfs树?其实是对于一棵仙人掌,dfs后形成生成树,找出非树边(即返祖边),然后dfs后每条返祖边+其所覆盖的链构成了一个环(很显然覆盖的链互不相交),然后可以确定每条边出现在哪个环中,然后可以解决一些简单的仙人掌DP问题,不用写tarjan了。
这道题的第一种方法就是dfs树DP,题目是求仙人掌的最大独立集。
首先树形DP,没有环应该很好求,有环的情况,考虑记录环上的点的top和end(注意环顶部不用记录,因为环顶部可能属于另一个环底)。然后可以直接DP了,相比于树形DP多记录一维环底部是否选,改成开两个数组,g[i][0/1]表示强制让环底部不选,该点不选/选的最大值,f[i][0/1]表示无所谓让环底部选不选,该点不选/选的最大值。首先对点u,初始化:f[u][1]=1,若不为环底部,则g[u][1]=1。dfs到边u->v,g[u][1]+=g[v][0],因为无论如何该点选了则儿子、底部势必不选,如果两点不在一个环上,则g[u][0]+=max(f[u][0],f[u][1]),反之g[u][0]+=max(g[v][0],g[v][1])。然后考虑转移f数组,首先f[u][0]+=max(f[v][0],f[v][1]),因为u不选,一切自由,如果u不为环的顶部,则f[u][1]+=f[v][0],反之,底部也不能选,f[u][1]+=g[v][0]。
贴不贴code也无所谓了,都说了这么多,不过还是贴一个吧。
#include<bits/stdc++.h>
using namespace std;
const int N=;
int n,m,dep[N],fa[N],tp[N],ed[N],f[N][],g[N][];
vector<int>G[N];
void dfs(int u)
{
dep[u]=dep[fa[u]]+;
for(int i=;i<G[u].size();i++)if(!dep[G[u][i]])fa[G[u][i]]=u,dfs(G[u][i]);
}
void walk(int u,int v){int x=v;while(x!=u)tp[x]=u,ed[x]=v,x=fa[x];}
void dp(int u)
{
f[u][]=;
if(u!=ed[u])g[u][]=;
for(int i=;i<G[u].size();i++)
if(dep[u]+==dep[G[u][i]])
{
int v=G[u][i];
dp(v);
if(ed[u]!=ed[v])g[u][]+=max(f[v][],f[v][]);else g[u][]+=max(g[v][],g[v][]);
g[u][]+=g[v][];
if(tp[v]!=u)f[u][]+=f[v][];else f[u][]+=g[v][];
f[u][]+=max(f[v][],f[v][]);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=,x,y;i<=m;i++)scanf("%d%d",&x,&y),G[x].push_back(y),G[y].push_back(x);
dfs();
for(int u=;u<=n;u++)
for(int i=;i<G[u].size();i++)
if(dep[u]+<dep[G[u][i]])walk(u,G[u][i]);
dp();
printf("%d",max(f[][],f[][]));
}
这题也可以仙人掌DP,当然不需要建立圆方树。tarjan的本质是构建dfs树,然后f[i][0/1]表示当前节点为i,不选/选的最大值,当边是树边时可以直接转移,反之暂时不转移。等到发现其为环的顶部时,然后从底部向顶部推一遍答案。由于是一条链,维护f0和f1表示当前其不选/选的最大值,然后推两遍即可,注意推一遍求f[u][1]时,强制不选底部,即f1=-inf,然后就是裸的树形DP了
#include<bits/stdc++.h>
using namespace std;
const int N=;
int n,m,cnt,dfn[N],low[N],fa[N],f[N][];
vector<int>G[N];
void dp(int u,int v)
{
int t0,t1,f0=,f1=;
for(int i=v;i!=u;i=fa[i])t0=f0+f[i][],t1=f1+f[i][],f0=max(t0,t1),f1=t0;
f[u][]+=f0;
f0=,f1=-1e9;
for(int i=v;i!=u;i=fa[i])t0=f0+f[i][],t1=f1+f[i][],f0=max(t0,t1),f1=t0;
f[u][]+=f1;
}
void tarjan(int u,int pre)
{
fa[u]=pre,dfn[u]=low[u]=++cnt;
f[u][]=,f[u][]=;
for(int i=;i<G[u].size();i++)
{
int v=G[u][i];
if(!dfn[v])tarjan(v,u),low[u]=min(low[u],low[v]);
else if(v!=pre)low[u]=min(low[u],dfn[v]);
if(low[v]>dfn[u])f[u][]+=f[v][],f[u][]+=max(f[v][],f[v][]);
}
for(int i=;i<G[u].size();i++)if(fa[G[u][i]]!=u&&dfn[u]<dfn[G[u][i]])dp(u,G[u][i]);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=,x,y;i<=m;i++)scanf("%d%d",&x,&y),G[x].push_back(y),G[y].push_back(x);
tarjan(,);
printf("%d",max(f[][],f[][]));
}
bzoj4316小C的独立集(dfs树/仙人掌+DP)的更多相关文章
- [BZOJ4316]小C的独立集 仙人掌?
题目链接 因为xls让我每周模拟一次,然后学习模拟中没有学过的东西.所以就来学圆方树. 本来这道题用不着圆方树,但是圆方树是看yyb的博客学的,他在里面讲一下作为一个引子,所以也来写一下. 首先来Ta ...
- 【题解】Bzoj4316小C的独立集
决定要开始学习圆方树 & 仙人掌相关姿势.加油~~ 其实感觉仙人掌本质上还是一棵树,长得也还挺优美的.很多的想法都可以往树的方面上靠,再针对仙人掌的特性做出改进.这题首先如果是在树上的话那么实 ...
- 2018.07.08 hdu4521 小明系列问题——小明序列(线段树+简单dp)
小明系列问题--小明序列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Proble ...
- [BZOJ4316]小C的独立集(圆方树DP)
题意:求仙人掌图直径. 算法:建出仙人掌圆方树,对于圆点直接做普通的树上DP(忽略方点儿子),方点做环上DP并将值直接赋给父亲. 建图时有一个很好的性质,就是一个方点在邻接表里的点的顺序正好就是从环的 ...
- BZOJ4316 小C的独立集 【仙人掌】
题目 图论小王子小C经常虐菜,特别是在图论方面,经常把小D虐得很惨很惨. 这不,小C让小D去求一个无向图的最大独立集,通俗地讲就是:在无向图中选出若干个点,这些点互相没有边连接,并使取出的点尽量多. ...
- 2019.02.07 bzoj4316: 小C的独立集(仙人掌+树形dp)
传送门 题意:给出一个仙人掌森林求其最大独立集. 思路:如果没有环可以用经典的树形dpdpdp解决. fi,0/1f_{i,0/1}fi,0/1表示第iii个点不选/选的最大独立集. 然后fi,0+ ...
- bzoj4316: 小C的独立集
Description 图论小王子小C经常虐菜,特别是在图论方面,经常把小D虐得很惨很惨. 这不,小C让小D去求一个无向图的最大独立集,通俗地讲就是:在无向图中选出若干个点,这些点互相没有边连接,并使 ...
- 树上独立集数量 树型DP
题目描述: 对于一棵树,独立集是指两两互不相邻的节点构成的集合.例如,图1有5个不同的独立集(1个双点集合.3个单点集合.1个空集),图2有14个不同的独立集,图3有5536个不同的独立集. 输入: ...
- hdu 4521 小明序列(线段树,DP思想)
题意: ①首先定义S为一个有序序列,S={ A1 , A2 , A3 , ... , An },n为元素个数 : ②然后定义Sub为S中取出的一个子序列,Sub={ Ai1 , Ai2 , Ai3 , ...
随机推荐
- 通过虚拟机增加Linux的磁盘(分区容量)
因为安装oracle设置的磁盘空间不足,所以安装失败.这里总结一下如何添加磁盘挂载 1. 右键虚拟机点击设置,然后点击磁盘,点击添加按钮 2.然后点击下一步下一步,直到安装成功 3.然后输入 fdis ...
- Redis原理详解
Redis原理详解 数据类型 Redis最为常用的数据类型主要有以下五种: String Hash List Set Sorted set 在具体描述这几种数据类型之前,我们先通过一张图了解下Redi ...
- sql数据库系统表和mysql系统表
sql数据库系统表,常用的(sysobjects,sysindexes,sysindexkeys,SYSCOLUMNS,SYSTYPES 及更多解释说明): https://docs.microsof ...
- emmmmmmmmmmmmmmmmmm01
当体会活着有多么难之后,就不要在那么随意的活着,今天有多么不在意自己的人生,明天就要加倍的被别的人左右自己的人生. 多思考,多学习,多总结,多创造.让自己成为有用的人,让自己未来有一天成为自己的主人.
- 8个最常用的Python内置函数,小白必备!
题图:Photo by Markus Spiske on Unsplash Python给我们内置了大量功能函数,官方文档上列出了69个,有些是我们是平时开发中经常遇到的,也有一些函数很少被用到,这里 ...
- HDU1007 Quoit Design掷环游戏
Quoit Design 看懂题意以后发现就是找平面最近点对间距离除以2. 平面上最近点对是经典的分治,我的解析 直接上代码 #include<bits/stdc++.h> using n ...
- xml配置文件解释
XML 指可扩展标记语言(EXtensible Markup Language) xmlns:是指XML命名空间 ( XML Namespace ) XSD是指XML结构定义 ( XML Schema ...
- (转)ERROR 2002 (HY000): Can't connect to local MySQL server through socket '***' (2)
有时候,当我们使用“mysql”.“mysqladmin”.“mysqldump”等命令管理数据库时,服务器抛出类似如下错误: 1 ERROR 2002 (HY000): Can't connect ...
- (转)zookeeper理解
分布式服务框架 Zookeeper -- 管理分布式环境中的数据 Zookeeper 分布式服务框架是 Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题 ...
- 107-PHP类成员属性赋值
<?php class mao{ //定义猫类 public $age; //定义多个成员属性 protected $weight; private $color; } $mao1=new ma ...