题目传送门:loj bzoj

  题意中的游戏方案可以转化为一个异或方程组的解,将边作为变量,点作为方程,因此若方程有解,方程的解的方案数就是2的自由元个数次方。我们观察一下方程,就可以发现自由元数量=边数-点数+连通块数,或者换句话说,若对原图的每个联通块指定一棵生成树,那么确定了生成树之外的边是否进行操作,那么生成树内的边的操作方案就是一定存在并唯一确定的。

  那么我们就只需要判断一下什么样的图无解。我们发现每对一条边进行操作,原图内的黑点数量奇偶性不变,那么我们只需判断图中的是否存在某个联通块有奇数个黑点,若存在即无解。

  加上了删点操作后,我们可以用圆方树来维护连通块信息。因为圆方树的连通性与原图上的连通性相互对应,删除单个点之后,原图被新分成的连通块就是圆方树删除对应点的连通块,那么使用圆方树就可以快速维护删除单个点的连通块信息。

  代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define ll long long
#define inf 0x3f3f3f3f
#define mod 1000000007
#define maxn 200010
inline ll read()
{
ll x=; char c=getchar(),f=;
for(;c<''||''<c;c=getchar())if(c=='-')f=-;
for(;''<=c&&c<='';c=getchar())x=x*+c-'';
return x*f;
}
inline void write(ll x)
{
static int buf[],len; len=;
if(x<)x=-x,putchar('-');
for(;x;x/=)buf[len++]=x%;
if(!len)putchar('');
else while(len)putchar(buf[--len]+'');
}
inline void writeln(ll x){write(x); putchar('\n');}
inline void writesp(ll x){write(x); putchar(' ');}
struct edge{
int to,nxt;
};
struct Graph{
edge e[*maxn];
int fir[*maxn],deg[*maxn];
int tot;
inline void clear()
{
memset(fir,,sizeof(fir)); tot=;
memset(deg,,sizeof(deg));
}
inline void add_edge(int x,int y)
{
e[tot].to=y; e[tot].nxt=fir[x]; fir[x]=tot++;
++deg[x];
}
}G,T;
int dfn[maxn],low[maxn],st[maxn],ans[maxn];
int val[*maxn],size[*maxn],fa[*maxn],rt[*maxn];
char s[maxn];
int n,m,tot,tp,cnt;
inline ll power(ll a,ll b)
{
ll ans=;
for(;b;b>>=,a=a*a%mod)
if(b&)ans=ans*a%mod;
return ans;
}
void tarjan(int now,int last)
{
dfn[now]=low[now]=++tot; st[++tp]=now;
for(int i=G.fir[now];~i;i=G.e[i].nxt)
if(i!=(last^)){
if(!dfn[G.e[i].to]){
tarjan(G.e[i].to,i);
low[now]=std::min(low[now],low[G.e[i].to]);
if(low[G.e[i].to]>=dfn[now]){
++cnt;
T.add_edge(now,cnt); T.add_edge(cnt,now);
do{
T.add_edge(st[tp],cnt); T.add_edge(cnt,st[tp]);
}while(st[tp--]!=G.e[i].to);
}
}
else low[now]=std::min(low[now],dfn[G.e[i].to]);
}
}
void dfs(int now,int root)
{
rt[now]=root;
size[now]=val[now];
for(int i=T.fir[now];~i;i=T.e[i].nxt)
if(T.e[i].to!=fa[now]){
fa[T.e[i].to]=now;
dfs(T.e[i].to,root);
size[now]+=size[T.e[i].to];
}
}
void work()
{
n=read(); m=read();
G.clear();
for(int i=;i<=m;i++){
int x=read(),y=read();
G.add_edge(x,y); G.add_edge(y,x);
}
scanf("%s",s);
memset(val,,sizeof(val));
for(int i=;i<=n;i++)
val[i]=(s[i-]=='');
T.clear();
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
tot=tp=; cnt=n;
for(int i=;i<=n;i++)
if(!dfn[i]){
tarjan(i,-);
fa[i]=-;
dfs(i,i);
}
int odd=,block=;
for(int i=;i<=n;i++)
if(fa[i]==-)odd+=(size[i]&),++block;
ans[]=(odd?:power(,m-n+block));
for(int i=;i<=n;i++){
odd-=(size[rt[i]]&);
int flag=;
for(int j=T.fir[i];~j;j=T.e[j].nxt)
if(T.e[j].to!=fa[i]&&(size[T.e[j].to]&)){
flag=; break;
}
if(odd||!flag||((size[rt[i]]-size[i])&))ans[i]=;
else ans[i]=power(,(m-G.deg[i])-(n-)+(block+T.deg[i]-));
odd+=(size[rt[i]]&);
}
for(int i=;i<=n;i++)
writesp(ans[i]);
putchar('\n');
}
int main()
{
int T=read();
while(T--)work();
return ;
}

反色游戏

【loj#2524】【bzoj5303】 [Haoi2018]反色游戏(圆方树)的更多相关文章

  1. [BZOJ5303] [HAOI2018] 反色游戏

    题目链接 LOJ:https://loj.ac/problem/2524 BZOJ:https://lydsy.com/JudgeOnline/problem.php?id=5303 洛谷:https ...

  2. [BZOJ5303][HAOI2018]反色游戏(Tarjan)

    暴力做法是列异或方程组后高斯消元,答案为2^自由元个数,可以得60分.但这个算法已经到此为止了. 从图论的角度考虑这个问题,当原图是一棵树时,可以从叶子开始唯一确定每条边的选择情况,所以答案为1. 于 ...

  3. 【BZOJ5303】[HAOI2018]反色游戏(Tarjan,线性基)

    [BZOJ5303][HAOI2018]反色游戏(Tarjan,线性基) 题面 BZOJ 洛谷 题解 把所有点全部看成一个\(01\)串,那么每次选择一条边意味着在这个\(01\)串的基础上异或上一个 ...

  4. bzoj 5393 [HAOI2018] 反色游戏

    bzoj 5393 [HAOI2018] 反色游戏 Link Solution 最简单的性质:如果一个连通块黑点个数是奇数个,那么就是零(每次只能改变 \(0/2\) 个黑点) 所以我们只考虑偶数个黑 ...

  5. P4494 [HAOI2018]反色游戏

    P4494 [HAOI2018]反色游戏 题意 给你一个无向图,图上每个点是黑色或者白色.你可以将一条边的两个端点颜色取反.问你有多少种方法每个边至多取反一次使得图上全变成白色的点. 思路 若任意一个 ...

  6. bzoj5315/luoguP4517 [SDOI2018]战略游戏(圆方树,虚树)

    bzoj5315/luoguP4517 [SDOI2018]战略游戏(圆方树,虚树) bzoj Luogu 题目描述略(太长了) 题解时间 切掉一个点,连通性变化. 上圆方树. $ \sum |S| ...

  7. BZOJ5329:[SDOI2018]战略游戏(圆方树,虚树)

    Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...

  8. [SDOI2018]战略游戏 圆方树,树链剖分

    [SDOI2018]战略游戏 这题是道路相遇(题解)的升级版,询问的两个点变成了\(S\)个点. LG传送门 还是先建出圆方树,考虑对于询问的\(S\)个点,答案就是圆方树上能包含这些点的最小连通块中 ...

  9. LOJ.2587.[APIO2018]铁人两项Duathlon(圆方树)

    题目链接 LOJ 洛谷P4630 先对这张图建圆方树. 对于S->T这条(些)路径,其对答案的贡献为可能经过的所有点数,那么我们把方点权值设为联通分量的大小,可以直接去求树上路径权值和. 因为两 ...

随机推荐

  1. [ML] Roadmap: a long way to go

    看上去不错的博文: 机器学习的经典算法一览 (一) 机器学习的经典算法一览 (二)       1.引言 正文将详细介绍传统机器学习算法,基本思想和用途.把问题解决思路和方法应用建议提前到这里的想法也 ...

  2. 图解 HTTP 笔记(四)——HTTP 状态码

    本章主要内容是了解 HTTP 状态码的工作机制 状态码的职责是当客户端向服务器端发送请求时,描述返回的请求结果.借助状态码,我们可以了解这次请求是否在服务器端得到了正常的处理. 状态码从其含以上可以分 ...

  3. HBase管理与监控——HMaster或HRegionServer自动停止挂掉

    问题描述 HBase在运行一段时间后,会出现以下2种情况: 1.HMaster节点自动挂掉: 通过jps命令,发现HMaster进程没了,只剩下HRegionServer,此时应用还能正常往HBase ...

  4. vs 扩展和更新下载的插件在什么位置呢,看看吧,哈哈

    C:\Users\Administrator\AppData\Local\Microsoft\VisualStudio\10.0\Extensions,注意哈,这个AppData是隐藏的哟,要显示才能 ...

  5. js 高级程序设计 第三章学习笔记——Number数据类型需要注意的事项

    1.浮点数值 虽然小数点前面可以没有整数,但是并不推荐这种写法. 由于保存浮点数值需要的内存空间是保存整数值的两倍,因此ECMAScript会不失时机地将浮点数值转化为整数数值.显然,如果小数点后面没 ...

  6. OLTP和 OLAP区别

    联机事务处理OLTP(on-line transaction processing) 主要是执行基本日常的事务处理,比如数据库记录的增删查改.比如在银行的一笔交易记录,就是一个典型的事务. OLTP的 ...

  7. hdoj1561 The more, The Better (树形dp,分组背包)

    题目链接:https://vjudge.net/problem/HDU-1561 题意:给一个森林,每个结点有个权值,求选m个结点的最大权值和,并且选子结点前必须先选父结点. 思路: 把每颗树的树根连 ...

  8. js中遍历对象的属性和值的方法

    鉴于循环目标是个对象,length是为undefined,用map等对数组的循环方法不行,对象就用此下方法 for(var key in _this.lists.medicines){ medicin ...

  9. Mybatis Plus带多条件的多表联合、分页、排序查询

    目录 一.现有表 student学生表: facultylist学院表: 二.同时满足以下需求: 1.多表联合查询出学院名字 2.可以带多条件查询 3.指定页码,页数据大小进行物理分页查询 三.解决步 ...

  10. 【转载】Jave开发手册之正则表达式预编译

    今天又水一篇,java开发手册华山版 一.编程规约 (九)其它 第一条 解释:Pattern要定义为static final静态变量,以避免执行多次预编译. 错误用法: // 没有使用预编译 priv ...