[BZOJ5287][HNOI2018]毒瘤(虚树DP)
暴力枚举非树边取值做DP可得75。
注意到每次枚举出一个容斥状态的时候,都要做大量重复操作。
建立虚树,预处理出虚树上两点间的转移系数。也可动态DP解决。
树上倍增、动态DP、虚树DP似乎是这种问题的三种通用解法。
代码不是特别长但极其难写,预处理过程中要考虑各种情况。水平不够只好抄代码。
#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
#define For(i,x) for (int i=h[x],k; i; i=nxt[i])
using namespace std; const int N=,mod=;
bool mark[N],vis[N],ban[N][];
int n,m,u,v,tot,tim,ans,sz[N],du[N],dv[N],dfn[N],dp[N][],g[N][];
struct P{ int k0,k1; }K[N][]; P operator +(const P &a,const P &b){ return (P){(a.k0+b.k0)%mod,(a.k1+b.k1)%mod}; }
P operator *(const P &a,int x){ return (P){int(1ll*a.k0*x%mod),int(1ll*a.k1*x%mod)}; } struct Edge{
int cnt,h[N],to[N<<],nxt[N<<];
P val[][];
void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
void add(int u,int v,const P &a,const P &b){
to[++cnt]=v; val[cnt][]=a; val[cnt][]=b; nxt[cnt]=h[u]; h[u]=cnt;
} void dfs1(int x,int fa){
dfn[x]=++tim;
For(i,x) if ((k=to[i])!=fa){
if (!dfn[k]) dfs1(k,x),sz[x]+=sz[k];
else if (dfn[k]<dfn[x]) du[++tot]=x,dv[tot]=k,mark[x]=mark[k]=;
}
mark[x]|=(sz[x]>=); if (mark[x]) sz[x]=;
} void dfs3(int x){
dp[x][]=ban[x][] ? : g[x][];
dp[x][]=ban[x][] ? : g[x][];
For(i,x){
dfs3(k=to[i]);
dp[x][]=1ll*dp[x][]*(1ll*val[i][].k0*dp[k][]%mod+1ll*val[i][].k1*dp[k][]%mod)%mod;
dp[x][]=1ll*dp[x][]*(1ll*val[i][].k0*dp[k][]%mod+1ll*val[i][].k1*dp[k][]%mod)%mod;
}
}
}G1,G2; int dfs2(int x){
g[x][]=g[x][]=; vis[x]=; int t=;
for (int i=G1.h[x],k; i; i=G1.nxt[i]) if (!vis[k=G1.to[i]]){
int z=dfs2(k);
if (!z) g[x][]=1ll*g[x][]*(g[k][]+g[k][])%mod,g[x][]=1ll*g[x][]*g[k][]%mod;
else{
if (mark[x]) G2.add(x,z,K[k][]+K[k][],K[k][]);
else K[x][]=K[k][]+K[k][],K[x][]=K[k][],t=z;
}
}
if (mark[x]) K[x][]=(P){,},K[x][]=(P){,},t=x;
else K[x][]=K[x][]*g[x][],K[x][]=K[x][]*g[x][];
return t;
} int main(){
freopen("bzoj5287.in","r",stdin);
freopen("bzoj5287.out","w",stdout);
scanf("%d%d",&n,&m);
rep(i,,m) scanf("%d%d",&u,&v),G1.add(u,v),G1.add(v,u);
G1.dfs1(,); mark[]=; dfs2();
for (int S=; S<(<<tot); S++){
rep(i,,tot) if (S&(<<(i-))) ban[dv[i]][]=,ban[du[i]][]=; else ban[dv[i]][]=;
G2.dfs3(); ans=(ans+(dp[][]+dp[][])%mod)%mod;
rep(i,,tot) if (S&(<<(i-))) ban[dv[i]][]=,ban[du[i]][]=; else ban[dv[i]][]=;
}
printf("%d\n",ans);
return ;
}
[BZOJ5287][HNOI2018]毒瘤(虚树DP)的更多相关文章
- BZOJ.5287.[AHOI HNOI2018]毒瘤(虚树 树形DP)
BZOJ LOJ 洛谷 设\(f[i][0/1]\)表示到第\(i\)个点,不选/选这个点的方案数.对于一棵树,有:\[f[x][0]=\prod_{v\in son[x]}(f[v][0]+f[v] ...
- bzoj 3572世界树 虚树+dp
题目大意: 给一棵树,每次给出一些关键点,对于树上每个点,被离它最近的关键点(距离相同被标号最小的)控制 求每个关键点控制多少个点 分析: 虚树+dp dp过程如下: 第一次dp,递归求出每个点子树中 ...
- bzoj 2286 [Sdoi2011]消耗战 虚树+dp
题目大意:多次给出关键点,求切断边使所有关键点与1断开的最小费用 分析:每次造出虚树,dp[i]表示将i和i子树与父亲断开费用 对于父亲x,儿子y ①y为关键点:\(dp[x]\)+=\(dismn( ...
- 【BZOJ】2286: [Sdoi2011]消耗战 虚树+DP
[题意]给定n个点的带边权树,每次询问给定ki个特殊点,求隔离点1和特殊点的最小代价.n<=250000,Σki<=500000. [算法]虚树+DP [题解]考虑普通树上的dp,设f[x ...
- [BZOJ2286][SDOI2011]消耗战(虚树DP)
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4998 Solved: 1867[Submit][Statu ...
- BZOJ 3572 [HNOI2014]世界树 (虚树+DP)
题面:BZOJ传送门 洛谷传送门 题目大意:略 细节贼多的虚树$DP$ 先考虑只有一次询问的情况 一个节点$x$可能被它子树内的一个到x距离最小的特殊点管辖,还可能被管辖fa[x]的特殊点管辖 跑两次 ...
- 洛谷P2495 [SDOI2011]消耗战(虚树dp)
P2495 [SDOI2011]消耗战 题目链接 题解: 虚树\(dp\)入门题吧.虚树的核心思想其实就是每次只保留关键点,因为关键点的dfs序的相对大小顺序和原来的树中结点dfs序的相对大小顺序都是 ...
- BZOJ5287 HNOI2018毒瘤(虚树+树形dp)
显然的做法是暴力枚举非树边所连接两点的选或不选,大力dp.考场上写的是最暴力的O(3n-mn),成功比大众分少10分.容斥或者注意到某些枚举是不必要的就能让底数变成2.但暴力的极限也就到此为止. 每次 ...
- 洛谷 P4426 - [HNOI/AHOI2018]毒瘤(虚树+dp)
题面传送门 神仙虚树题. 首先考虑最 trival 的情况:\(m=n-1\),也就是一棵树的情况.这个我相信刚学树形 \(dp\) 的都能够秒掉罢(确信).直接设 \(dp_{i,0/1}\) 在表 ...
随机推荐
- UNIX网络编程 第8章 基本UDP套接字编程
UDP是无连接的,不需要accept,TCP通过accept API来接受连接,并且将连接客户端的信息写入到accept将返回的新socket中,该新socket中有服务端和客户端的IP地址和端口,因 ...
- AS中一些不经常用到的快捷键
1 书签 添加/移除书签 Ctrl+shift+F11 展示书签 shift+F11 下一个书签 shift+加号 上一个书签 shift+减号 2 折叠/展开代码块 展开代码块 ctrl+加号 ...
- 【codeforces】【比赛题解】#950 CF Round #469 (Div. 2)
剧毒比赛,至少涨了分对吧.: ( [A]Left-handers, Right-handers and Ambidexters 题意: 有\(l\)个右撇子,\(r\)个左撇子,\(a\)个双手都惯用 ...
- linux下补丁制作及打补丁实例【转】
转自:http://www.latelee.org/using-gnu-linux/diff-and-patch-on-linux.html 搞ARM有一段时日了,期间看了不少开发板的手册,手册的内容 ...
- vue引入elementUI 报错
在main.js里面引入import 'element-ui/lib/theme-default/index.css'中报错,无法启动项目,这是把package.json里面的webpack改成 1 ...
- 在JAVA中记录日志的十个小建议
JAVA日志管理既是一门科学,又是一门艺术.科学的部分是指了解写日志的工具以及其API,而选择日志的格式,消息的格式,日志记录的内容,哪种消息对应于哪一种日志级别,则完全是基于经验.从过去的实践证明, ...
- python网络编程--线程递归锁RLock
一:死锁 所谓死锁:是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进 ...
- 3.Springboot之修改启动时的默认图案Banner
一.SpringBoot的默认启动图案 在SpringBoot启动的时候,默认的会展示出一个spring的logo,这个图案我们用户是可以自定义的 二.自定义启动图案 方法一: Application ...
- No.6 selenium学习之路之下拉框Select
HTML中,标签显示为select,有option下拉属性的为Select弹框 1.Xpath定位 Xpath语法,顺序是从1开始,编程语言中是0开始
- 如何在VS2013创建WebService并在IIS中发布
第一步:打开VS2013,选择文件->新建->项目. 第二步:选择[ASP.net 空web应用程序],将其命名为自己想的工程名称. 第三步:然后右键点击工程,添加->web服务.然 ...