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 , ...
随机推荐
- 洛谷 P1247 取火柴游戏
题目传送门 暴力 \((\)由于我这样的初中蒟蒻不\((bu)\)喜\((hui)\)欢\((xie)\)数学证明,所以题解中的证明全是其他大佬的题解已经多次证明过的,这里就不再啰嗦了.\()\) - ...
- es678910语法糖
傲娇: 新es是js的进步,是编程的进步,es6已经过去了5年了,兼容率达到了90%,还是有10%的手机不兼容,那到底应不应该去照顾那些跟不上的人,我觉得是不应该的,新es能5行写出来的功能,我为什么 ...
- Vue(十)---路由
Vue.js 路由允许我们通过不同的 URL 访问不同的内容.通过 Vue.js 可以实现多视图的单页Web应用(single page web application,SPA). 需要引入vue-r ...
- PHPExcel方法总结
下面是总结的几个使用方法include 'PHPExcel.php';include 'PHPExcel/Writer/Excel2007.php';//或者include 'PHPExcel/Wri ...
- 016.CI4框架CodeIgniter数据库操作之:Insert插入一条数据
01.在Model中,写入插入的语句 <?php namespace App\Models\System; use CodeIgniter\Model; class User_model ext ...
- leetcode1302 Deepest Leaves Sum
""" Given a binary tree, return the sum of values of its deepest leaves. Example 1: I ...
- Ubuntu 1804 进入紧急模式
进入系统引导前,长按shift键: 选择第一条,按e进入编辑 添加完成后,只需按下 CTRL+x 或 F10 即可继续启动救援模式 接下来,输入以下命令将根 (/) 文 ...
- OpenMandriva或将放弃32位的支持
导读 除了Ubuntu计划在其19.10发行版中删除32位包之外,OpenMandriva开发团队也是另一个备受关注的Linux发行版起草计划,以取消对32位包的支持. OpenMandriva计划在 ...
- 2.13 ViewModel 使数据即使在后台被杀死数据也能存活
操作程序如下: 主要是创建一个 SavedStateHandle 来缓存上一次的数据,并通过重新读取上一次存储的数据来实现数据的存活 MyVIewModel: package com.example. ...
- MSP430系列单片机笔记00
嵌入式系统 嵌入式系统(Embedded system),是一种“完全嵌入受控器件内部,为特定应用而设计的专用计算机系统”,根据英国电气工程师协会( U.K. Institution of Elect ...