BZOJ5287 HNOI2018毒瘤
Problem
BZOJ
Solution
顾名思义,如果不是暴力分比较多,的确是一道很毒瘤的题。。
题面中所谓的联通操作就是保证互斥的连边后,是一个连通图。我们从树的状态考虑起。不妨设f[x][1/0]表示子树x中x选/不选时合法的方案数。
容易得到转移方程f[x][1]=∏f[son][0],f[x][0]=∏(f[son][0]+f[son][1])f[x][1]=∏f[son][0],f[x][0]=∏(f[son][0]+f[son][1])f[x][1]=\prod f[son][0],f[x][0]=\prod (f[son][0]+f[son][1])
那么对于加入的非树边应该怎么办呢,我们可以去掉环上的一边,使得它变成树,将这个边的作用看做约束条件,即x,y不能同时选中。注意到此时有合法的三种状态即(1,0),(0,1),(0,0),那么我们对每条非树边枚举状态再DP算贡献,时间复杂度为O(3m−n+1n)O(3m−n+1n)O(3^{m-n+1}n)
我们可以把状态合并成两个状态,改成枚举dfs序更小的点选不选,因为当它不选时,另一个点可以选也可以不选,合并起来转移即可做到O(2m−n+1n)O(2m−n+1n)O(2^{m-n+1}n)。这个时候的暴力分已经很多了。
如果你大力推公式,你可以发现,除了非树边约束的两个点,其它的dp都可以预处理转移的系数。那么我们考虑建立一棵虚树,然后dfs暴力转移出系数,并把系数关系化成虚树上边的权值,然后就可以做了。时间复杂度是s=m−n+1,O(n+s2s)s=m−n+1,O(n+s2s)s=m-n+1,O(n+s2^s)。
Code
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=100100,mod=998244353;
inline int pls(int x,int y){return x+y>=mod?x+y-mod:x+y;}
template <typename Tp> inline void read(Tp &x)
{x=0;int f=0;char ch=getchar();while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();if(ch=='-') f=1,ch=getchar();while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();if(f) x=-x;
}
struct data{int v,nxt;}edge[maxn<<1];
struct factor{int x,y;factor(){}factor(int _x,int _y){x=_x;y=_y;}factor operator + (const factor &t){return factor(pls(x,t.x),pls(y,t.y));}factor operator * (const int t){return factor((ll)x*t%mod,(ll)y*t%mod);}
}k[maxn][2];
struct data2{int v,nxt;factor a,b;}ed[maxn];
int n,m,ep,edp,ans,dfc,cnt,head[maxn],h[maxn],dfn[maxn],mark[maxn],sz[maxn];
int vis[maxn],p[maxn][2],st[maxn][2],f[maxn][2];
pii e[20];
inline void insert(int u,int v){edge[++ep]=(data){v,head[u]};head[u]=ep;}
inline void insert(int u,int v,factor a,factor b)
{ed[++edp]=(data2){v,h[u],a,b};h[u]=edp;
}
int dfs(int x,int pre)
{dfn[x]=++dfc;for(int i=head[x];i;i=edge[i].nxt)if(edge[i].v^pre){if(!dfn[edge[i].v]) sz[x]+=dfs(edge[i].v,x);//sz表示有几棵子树中有虚树节点else{mark[x]=1;//mark标记虚树节点if(dfn[edge[i].v]>dfn[x]) e[++cnt]=make_pair(x,edge[i].v);}}mark[x]|=(sz[x]>1);//这说明x是虚树上的一个lcareturn sz[x]||mark[x];
}
int build(int x)
{int pos=0,w,v;p[x][0]=p[x][1]=1;vis[x]=1;//p是自己的dp,k用于累加虚树边的系数for(int i=head[x];i;i=edge[i].nxt)if(!vis[edge[i].v]){v=edge[i].v;w=build(v);if(!w){p[x][0]=(ll)p[x][0]*pls(p[v][0],p[v][1])%mod;p[x][1]=(ll)p[x][1]*p[v][0]%mod;}else if(mark[x]) insert(x,w,k[v][0]+k[v][1],k[v][0]);else k[x][0]=k[v][0]+k[v][1],k[x][1]=k[v][0],pos=w;//此时只会有一个虚树节点,否则mark[x]=1}if(mark[x]) k[x][0]=factor(1,0),k[x][1]=factor(0,1),pos=x;else k[x][0]=k[x][0]*p[x][0],k[x][1]=k[x][1]*p[x][1];return pos;//子树中深度最小的虚树节点
}
void input()
{int x,y;read(n);read(m);for(int i=1;i<=m;i++){read(x);read(y);insert(x,y);insert(y,x);}dfs(1,0);mark[1]=1;build(1);
}
void dp(int x)
{int f0,f1;f[x][0]=st[x][1]?0:p[x][0];f[x][1]=st[x][0]?0:p[x][1];for(int i=h[x];i;i=ed[i].nxt){dp(ed[i].v);f0=f[ed[i].v][0];f1=f[ed[i].v][1];f[x][0]=(ll)f[x][0]*pls((ll)ed[i].a.x*f0%mod,(ll)ed[i].a.y*f1%mod)%mod;f[x][1]=(ll)f[x][1]*pls((ll)ed[i].b.x*f0%mod,(ll)ed[i].b.y*f1%mod)%mod;}
}
int main()
{#ifndef ONLINE_JUDGEfreopen("in.txt","r",stdin);#endifinput();int lim=1<<cnt;for(int i=0;i<lim;i++){for(int j=1;j<=cnt;j++){if(i&(1<<j-1)) st[e[j].first][1]=st[e[j].second][0]=1;else st[e[j].first][0]=1;}dp(1);ans=pls(ans,pls(f[1][0],f[1][1]));for(int j=1;j<=cnt;j++){if(i&(1<<j-1)) st[e[j].first][1]=st[e[j].second][0]=0;else st[e[j].first][0]=0;}}printf("%d\n",ans);return 0;
}
BZOJ5287 HNOI2018毒瘤相关推荐
- # HNOI2012 ~ HNOI2018 题解
HNOI2012 题解 [HNOI2012]永无乡 Tag:线段树合并.启发式合并 联通块合并问题. 属于\(easy\)题,直接线段树合并 或 启发式合并即可. [HNOI2012]排队 Tag:组 ...
- yyb省选前的一些计划
突然意识到有一些题目的计划,才可以减少大量查水表或者找题目的时间. 所以我决定这样子处理. 按照这个链接慢慢做. 当然不可能只做省选题了. 需要适时候夹杂一些其他的题目. 比如\(agc/arc/cf ...
- HNOI2018 摸鱼记
HNOI2018 摸鱼记 今天我又来记流水账啦 Day 0 颓废的一天. 我,球爷和杜教在颓膜膜.io ych看起来在搓碧蓝 鬼知道哥达鸭干了什么 学习氛围只局限在机房的一角 后来全体Oier开会,5 ...
- [BZOJ3337] ORZJRY I --块状链表大毒瘤
link 题目大意:维护一个序列 支持: 1.单点插入 2.单点删除 3.区间翻转 4.区间旋转 5.区间加 6.区间赋值 7.询问区间和 8.询问区间极差 9.询问区间与给定某个数差值绝对值的最小值 ...
- 毒瘤题No.006-byFHS
毒瘤题No.006-byFHS 题目背景 暂无 题目描述 给你一个无向图,求最少用多少棵树来覆盖这个图上的所有边 输入格式 第1行:两个数\(n,m\),表示有\(n\)个点,\(m\)条边 接下来\ ...
- 约会安排 (区间合并)毒瘤题
约会安排 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total Submi ...
- 「AHOI / HNOI2018」转盘 解题报告
「AHOI / HNOI2018」转盘 可能是我语文水平不太行... 首先可以猜到一些事实,这个策略一定可以被一个式子表示出来,不然带修修改个锤子. 然后我们发现,可以枚举起点,然后直接往前走,如果要 ...
- 【UOJ#67】新年的毒瘤 Tarjan 割点
#67. 新年的毒瘤 UOJ直接黏贴会炸... 还是戳这里吧: http://uoj.ac/problem/67#tab-statement Solution 看到这题的标签就进来看了一眼. 想 ...
- HNOI2018游记
HNOI2018游记 day 0 上午稍微写了下题保持手感,然后看了一下套路,感觉不会的还是不会. 下午去划水在湖面上被吹成傻逼... 感觉没有联赛前那么紧张了,应该是联赛考挂了的原因吧.. day1 ...
- Potato的暑期训练day#1题解 ——毒瘤构造
Potato的暑期训练day#1 --毒瘤构造 题目链接: A.https://vjudge.net/problem/HDU-1214 B.https://vjudge.net/problem/Cod ...
最新文章
- SUSE LINUX下文件系统变只读的问题解决
- 内部人看FaceBook
- 项目:网站架构,集群
- Alpha 冲刺 (7/10)
- 使用ffmpeg进行h.264编码
- .net winform panel 不刷新_winform项目——仿QQ即时通讯程序04:登录界面补充
- java mysql存储图片_Java存储图片到Mysql
- Windows开启SSH连接
- 如何统计网页的浏览量?Steins
- [lua]紫猫lua教程-命令宝典-L1-01-09. string字符串函数库
- 【Windows】win7虚拟机安装VMware Tools
- 重定向与重定位的理解
- JavaWeb期末考试复习资料
- 【避坑指“难”】页面Top置顶(返回顶部)小图标实现逻辑
- 支付宝小程序模板开发,协助商家一键创建小程序
- labview2015安装DAQmx助手之后无法使用的问题
- 如何使用svn导出项目
- 移动端网页打印代码_安卓移动端直接打印文档方法,无需开电脑
- 索引全扫描与索引快速扫描的区别
- 【2022考研最后40天】要注意这4个时间节点和这5件事情
热门文章
- 360 路由器设置 虚拟服务器,360安全路由器的设置方法
- 如何实现不规则的Div外部形状?
- 原价游戏太贵?爬取steam游戏优惠信息
- 13.2.3 VAM服务器的配置步骤及示例(2)
- 微信表情的字符编号完整版【图文并茂哦 】
- an error occurred while creating opening the c++ browsing database 解决办法
- snappy流式编解码总结
- ZZULIOJ:1132: 数字字符统计
- java与设计模式-观察者模式
- c++学习笔记 第四部分