洛谷P4494 [HAOI2018]反色游戏(tarjan)
题面
题解
我们先来考虑一个联通块,这些关系显然可以写成一个异或方程组的形式,形如\(\oplus_{e\in edge_u}x_e=col_u\)
如果这个联通块的黑色点个数为奇数,那么显然这个方程是无解的
证明:每条边都在方程组的左边出现了两次,左边全部异或起来为\(0\),右边全部异或起来为\(1\),显然无解
那么如果这个方程组有解,解的个数就是\(2^{自由元数目}\)
我们随便求出这个联通块的一棵生成树,把所有树边当成自由元,容易发现对于非树边的每一种选法,树边都有一种唯一对应的选择方案使其合法,设这个联通块边数为\(m\),点数为\(n\),方案数就是\(2^{m-n+1}\)
进一步可得知\(c\)个联通块的方案数为\(2^{m-n+c}\)次,且与联通块内部连边无关
然后是对于每个点的询问,先判一下删掉之后的联通块中是否会有奇数个黑色点,如果合法的话就减去它周围的边数减去它自己的点数再加上新的联通块数即可
//minamoto
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
int read(char *s){
R int len=0;R char ch;while(((ch=getc())>'1'||ch<'0'));
for(s[++len]=ch;(ch=getc())>='0'&&ch<='1';s[++len]=ch);
return s[len+1]='\0',len;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R int x){
if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]=' ';
}
const int N=1e5+5,P=1e9+7;
struct eg{int v,nx;}e[N<<1];int head[N],tot;
inline void Add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
int dfn[N],low[N],sz[N],deg[N],ok[N],cut[N],rt[N],bin[N],sub[N];char s[N];
int n,m,u,v,tim,Rt,cnt,odd;
void tarjan(int u,int fa){
sz[u]=s[u]-'0',dfn[u]=low[u]=++tim,ok[u]=cut[u]=sub[u]=0,rt[u]=Rt;
go(u)if(!dfn[v]){
tarjan(v,u),sz[u]+=sz[v],cmin(low[u],low[v]);
low[v]>=dfn[u]?++cut[u],ok[u]|=(sz[v]&1),sub[u]+=sz[v]:0;
}else if(v!=fa)cmin(low[u],dfn[v]);
!fa?--cut[u]:0;
}
void clr(){
memset(dfn,0,sizeof(int)*(n+1)),tim=0;
memset(head,0,sizeof(int)*(n+1)),tot=0;
memset(deg,0,sizeof(int)*(n+1));
}
int main(){
// freopen("testdata.in","r",stdin);
bin[0]=1;fp(i,1,1e5)bin[i]=(bin[i-1]<<1)%P;
for(int T=read();T;--T){
n=read(),m=read();
fp(i,1,m)u=read(),v=read(),++deg[u],++deg[v],Add(u,v),Add(v,u);
read(s),cnt=m-n,odd=0;
fp(i,1,n)if(!dfn[i])Rt=i,tarjan(i,0),++cnt,odd+=(sz[i]&1);
print(odd?0:bin[cnt]);
fp(i,1,n)print((ok[i]||(odd-(sz[rt[i]]&1))||((sz[rt[i]]-s[i]-'0'-sub[i])&1))?0:bin[cnt-deg[i]+cut[i]+1]);
// fp(i,1,n)if(cnt-deg[i]+cut[i]+1>=1e5)puts("qwq");
sr[C]='\n',clr();
}
return Ot(),0;
}
洛谷P4494 [HAOI2018]反色游戏(tarjan)的更多相关文章
- P4494 [HAOI2018]反色游戏
P4494 [HAOI2018]反色游戏 题意 给你一个无向图,图上每个点是黑色或者白色.你可以将一条边的两个端点颜色取反.问你有多少种方法每个边至多取反一次使得图上全变成白色的点. 思路 若任意一个 ...
- [BZOJ5303][HAOI2018]反色游戏(Tarjan)
暴力做法是列异或方程组后高斯消元,答案为2^自由元个数,可以得60分.但这个算法已经到此为止了. 从图论的角度考虑这个问题,当原图是一棵树时,可以从叶子开始唯一确定每条边的选择情况,所以答案为1. 于 ...
- 【BZOJ5303】[HAOI2018]反色游戏(Tarjan,线性基)
[BZOJ5303][HAOI2018]反色游戏(Tarjan,线性基) 题面 BZOJ 洛谷 题解 把所有点全部看成一个\(01\)串,那么每次选择一条边意味着在这个\(01\)串的基础上异或上一个 ...
- bzoj 5393 [HAOI2018] 反色游戏
bzoj 5393 [HAOI2018] 反色游戏 Link Solution 最简单的性质:如果一个连通块黑点个数是奇数个,那么就是零(每次只能改变 \(0/2\) 个黑点) 所以我们只考虑偶数个黑 ...
- 【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 ...
- bzoj 5303: [Haoi2018]反色游戏
Description Solution 对于一个有偶数个黑点的连通块,只需要任意两两配对,并把配对点上的任一条路径取反,就可以变成全白了 如果存在奇数个黑点的连通块显然无解,判掉就可以了 如果有解, ...
- [HAOI2018]反色游戏
[Luogu4494] [BZOJ5303] [LOJ2524] LOJ有数据就是好 原题解,主要是代码参考 对于每一个联通块(n个点),其他的边一开始随便选,只需要n-1条边就可以确定最终结果. 所 ...
- 题解 [HAOI2018]反色游戏
题目传送门 题目大意 给出一个 \(n\) 个点 \(m\) 条无向边的图,每个点都有一个 \(\in [0,1]\) 的权值,每次可以选择一条边,然后将该边相连两点权值异或上 \(1\).问有多少种 ...
随机推荐
- day1--心得
info = ''' --------------------info of %s---------------- name: %s age: %s job: %s ----------------- ...
- Python基础学习四 列表、元组、字典、集合
列表list,用中括号“[ ]”表示 1.任意对象的有序集合 列表是一组任意类型的值,按照一定顺序组合而成的 2.通过偏移读取 组成列表的值叫做元素(Elements).每一个元素被标识一个索引,第一 ...
- beijing
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<graphics.h> ...
- collections、time和datetime模块
主要内容: 一.collections模块 二.time模块 三.datetime模块 1️⃣ collection模块 1.什么是collections模块.干什么用? collections模块 ...
- codeforce 460DIV2 D题
感觉这个题不错,对拓扑排序有了更深的了解,用两种拓扑排序都写了些试试. dfs #include <cstdio> #include <algorithm> #include ...
- fhq-treap模板
模板保存. #include<iostream> #include<cstdio> #include<cstring> #include<ctime> ...
- 运单waybill快速录入
运单waybill快速录入 前台页面: 1修改页面onAfterEdit事件, 后台代码:ajax响应回请求1 为成功,0 为失败
- Linux ekho
一.简介 Ekho(余音)是一个免费.开源的中文语音合成软件.它目前支持粤语.普通话(国语).诏安客语.藏语.雅言(中国古代通用语)和韩语(试验中),英文则通过Festival间接实现.Ekho支持L ...
- 2、awk的输出
1.常见的输出格式整理 awk '{print "this is " $1, $2, $1*$2, NR, NF, $NF}' file1 ###字符输出,字段输出,运算输出, ...
- 1.scala基础语法总结
Scala基础语法总结:Scala 与 Java 的最大区别是:Scala 语句末尾的分号 ; 是可选的.如果一行里写多个语句那么分号是需要的 val s = "菜鸟教程"; pr ...