题解 [HAOI2018]反色游戏
题目大意
给出一个 \(n\) 个点 \(m\) 条无向边的图,每个点都有一个 \(\in [0,1]\) 的权值,每次可以选择一条边,然后将该边相连两点权值异或上 \(1\)。问有多少种选择方法使得每个点的权值都变为 \(0\)。(每条边只能选择一次)
但是这个问题太简单了,所以你要求删掉每个点以及它连出的边之后的答案。
有 \(t\) 组数据,\(t\le 5,n,m\le 10^5\)。
思路
这道题不是很难写,但是很难想。
我们先考虑一棵树的答案,你发现这样方案是唯一的,因为你从叶子节点开始考虑,如果当前点是黑的,那就选择父亲边,否则就不能选。然后你发现有解的充要条件就是黑点是偶数个。
考虑一个 \(n\) 点 \(m\) 边的连通图,你发现如果我们钦点出 \(n-1\) 条边作为树边,那么它们是惟一的。对于剩下的 \(m-n+1\) 条边,你可以任意选择要或不要(相当于改变两个点的初始颜色),然后改变那 \(n-1\) 条边使得合法即可。所以答案就是 \(2^{m-n+1}\) ,判断有解的方法同上。
对于一个不连通图,你发现如果有解的话答案就是 \(2^{m-n+t}\)。其中 \(t\) 是连通块个数。显然。
考虑删掉一个点以及相连的边后的方案数,实际上就是如何判断合不合法以及删掉之后的连通块个数。
- 连通块个数
你发现这个东西只跟割边有关,设 \(\text{cnt}(i)\) 表示点 \(i\) 在 \(\text{dfs}\) 树上与儿子节点相连的割边个数,你发现答案连通块个数就增加了 \(\text{cnt}(i)\) 个。(如果 \(i=\text{root}\) 的话 \(\text{cnt}(i)\) 需要减 \(1\) 因为它连通块增加个数会少一个,因为它没有父亲)
- 判断合法性
首先需要判断除了该点所属外的连通块的合法性。
然后判断分出来的子树合法性。
然后判断剩下的一块合法性就好了。
合法性判断同上文,看连通块里面 \(1\) 的个数就好了。
用 \(\text{Tarjan}\) 实现,时间复杂度 \(\Theta(Tn)\)。
\(\texttt{Code}\)
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define mod 1000000007
#define MAXN 100005
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
vector <int> G[MAXN];
int n,m,rt,ind,a[MAXN],f[MAXN],d[MAXN],bin[MAXN],dfn[MAXN],low[MAXN],deg[MAXN],cnt[MAXN],bel[MAXN],sum[MAXN];
void Link (int x,int y){
deg[x] ++,deg[y] ++;
G[x].push_back (y),G[y].push_back (x);
}
void Tarjan (int u){
bel[u] = rt,dfn[u] = low[u] = ++ ind,sum[u] = a[u];
for (Int v : G[u]){
if (!dfn[v]){
Tarjan (v);
sum[u] += sum[v];
low[u] = min (low[u],low[v]);
if (low[v] >= dfn[u]) cnt[u] ++,f[u] += sum[v],d[u] |= (sum[v] & 1);//u->v是割边
}
else low[u] = min (low[u],dfn[v]);
}
cnt[u] -= (u == rt);
}
signed main(){
int t;read (t);
bin[0] = 1;for (Int i = 1;i <= MAXN - 5;++ i) bin[i] = 2 * bin[i - 1] % mod;
while (t --> 0){
read (n,m);int val = 0,tot = 0;
for (Int i = 1,u,v;i <= m;++ i) read (u,v),Link (u,v);
for (Int i = 1;i <= n;++ i) scanf ("%1d",&a[i]);
for (Int i = 1;i <= n;++ i) if (!dfn[i]) rt = i,Tarjan (i),tot ++,val += (sum[i] & 1);
write (val ? 0 : bin[m - n + tot]);
for (Int i = 1;i <= n;++ i){
putchar (' ');
if (d[i]) putchar ('0');
else if (val - (sum[bel[i]] & 1)) putchar ('0');
else if ((sum[bel[i]] - f[i] - a[i]) & 1) putchar ('0');
else write (bin[(m - deg[i]) - (n - 1) + tot + cnt[i]]);
}
putchar ('\n'),ind = 0;
for (Int i = 1;i <= n;++ i) G[i].clear (),f[i] = d[i] = cnt[i] = deg[i] = dfn[i] = low[i] = 0;
}
return 0;
}
题解 [HAOI2018]反色游戏的更多相关文章
- 【BZOJ5303】[HAOI2018]反色游戏(Tarjan,线性基)
[BZOJ5303][HAOI2018]反色游戏(Tarjan,线性基) 题面 BZOJ 洛谷 题解 把所有点全部看成一个\(01\)串,那么每次选择一条边意味着在这个\(01\)串的基础上异或上一个 ...
- bzoj 5393 [HAOI2018] 反色游戏
bzoj 5393 [HAOI2018] 反色游戏 Link Solution 最简单的性质:如果一个连通块黑点个数是奇数个,那么就是零(每次只能改变 \(0/2\) 个黑点) 所以我们只考虑偶数个黑 ...
- P4494 [HAOI2018]反色游戏
P4494 [HAOI2018]反色游戏 题意 给你一个无向图,图上每个点是黑色或者白色.你可以将一条边的两个端点颜色取反.问你有多少种方法每个边至多取反一次使得图上全变成白色的点. 思路 若任意一个 ...
- 【loj#2524】【bzoj5303】 [Haoi2018]反色游戏(圆方树)
题目传送门:loj bzoj 题意中的游戏方案可以转化为一个异或方程组的解,将边作为变量,点作为方程,因此若方程有解,方程的解的方案数就是2的自由元个数次方.我们观察一下方程,就可以发现自由元数量=边 ...
- [BZOJ5303] [HAOI2018] 反色游戏
题目链接 LOJ:https://loj.ac/problem/2524 BZOJ:https://lydsy.com/JudgeOnline/problem.php?id=5303 洛谷:https ...
- [BZOJ5303][HAOI2018]反色游戏(Tarjan)
暴力做法是列异或方程组后高斯消元,答案为2^自由元个数,可以得60分.但这个算法已经到此为止了. 从图论的角度考虑这个问题,当原图是一棵树时,可以从叶子开始唯一确定每条边的选择情况,所以答案为1. 于 ...
- 洛谷P4494 [HAOI2018]反色游戏(tarjan)
题面 传送门 题解 我们先来考虑一个联通块,这些关系显然可以写成一个异或方程组的形式,形如\(\oplus_{e\in edge_u}x_e=col_u\) 如果这个联通块的黑色点个数为奇数,那么显然 ...
- [HAOI2018]反色游戏
[Luogu4494] [BZOJ5303] [LOJ2524] LOJ有数据就是好 原题解,主要是代码参考 对于每一个联通块(n个点),其他的边一开始随便选,只需要n-1条边就可以确定最终结果. 所 ...
- bzoj 5303: [Haoi2018]反色游戏
Description Solution 对于一个有偶数个黑点的连通块,只需要任意两两配对,并把配对点上的任一条路径取反,就可以变成全白了 如果存在奇数个黑点的连通块显然无解,判掉就可以了 如果有解, ...
随机推荐
- canvas——绘制解锁图案
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- Python3-sqlalchemy-orm
1 #-*-coding:utf-8-*- 2 #__author__ = "logan.xu" 3 4 5 import sqlalchemy 6 from sqlalchemy ...
- 浅析 Dapr 里的云计算设计模式
Dapr 实际上是把分布式系统 与微服务架构实践的挑战以及k8s 这三个主题的全方位的设计组合,特别是Kubernetes设计模式 一书作者Bilgin Ibryam 提出的Multi-Runtime ...
- Windows系统一些好用的办公工具
在日常办公过程中,总有一些工具令人觉得方便,提高了工作效率.以下是根据我的习惯,收集了一些好用的工具,在此记录且不定期更新. 文件名 说明 Everything 文件搜索工具,搜索速度快 ALTRun ...
- C# 爬虫框架实现 流程_爬虫结构/原理
目录链接:C# 爬虫框架实现 概述 首先需要讲的是,爬虫的原理.其实在我看来,爬虫只是用来解决以下四个问题的工具: 提取哪些网页 提取网页上的哪些内容 存储到哪里(推荐数据库/开源类/Console) ...
- 20210712考试-2021noip11
这篇总结比我写的好多了建议直接去看 T1 简单的序列 考场:愣了一会,想到以最大值分治.每次枚举最大值两侧更小的区间,st表预处理前缀和和最大值,用桶统计答案. 注意分治时要去掉最大值. const ...
- Docker(40)- docker 实战三之安装 ES+Kibana
背景 参考了狂神老师的 Docker 教程,非常棒! https://www.bilibili.com/video/BV1og4y1q7M4?p=16 es 前言 es 暴露的端口很多 es 十分耗内 ...
- springcloud3(五) spring cloud gateway动态路由的四类实现方式
写这篇博客主要是为了汇总下动态路由的多种实现方式,没有好坏之分,任何的方案都是依赖业务场景需求的,现在网上实现方式主要有: 基于Nacos, 基于数据库(PosgreSQL/Redis), 基于Mem ...
- python爬区csdn文章信息(原始稿)
使用python对csdn的博主文章进行爬取,期间又遇到了新的问题和旧的已经遇到过的问题.首先做一个笔记,免得以后遇到同样的问题时还得浪费时间和经历. 刚开始目的没那么明确,主要在于熟悉相关的规则及流 ...
- 记录一下Vray5中文汉化版本中导出EXR或vrimg多通道文件的那些坑和解决方法
最近在给一个培训机构代课,学生英语基础差,就安装了Vray5的中文版,噩梦从此开始. 做过合成的都知道,需要输出多通道到NUKE或者AE中进行合成,通常情况下把多个pass分成不同的文件对硬盘反复读写 ...