bzoj 5303: [Haoi2018] Reverse color game

Description

Solution

For a connected block with an even number of black points, it only needs to be paired in any pair, and invert a path on the paired point, it can become completely white.
If there is a connected block with an odd number of black points, it is obvious that there is no solution. If there is a
solution, the number of solutions must be the same.
There are a total of \(2^{m}\) kinds of coloring schemes, there are \(2^{n-1}\) to dye the point into an even number of white scheme, because each scheme can produce the same solution, then there are \(2^{m-n+1}\) solutions
, so the contribution to each connected block is \(2^{m- n+1}\) , if there are \(c\) connected blocks, the answer is \(2^{m-n+p}\) After deleting a
point, you only need to judge whether there is a new The number of black dots in connected blocks is an even number, and you can know the answer by counting the number of connected blocks.

#include<bits/stdc++.h>
using namespace std;
template<class T>void gi(T &x){
    int f;char c;
    for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
    for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
}
const int N=1e5+10,mod=1e9+7;
int n,m,head[N],nxt[N*2],to[N*2],num=0,ID=0,in[N];
inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
int dfn[N],low[N],DFN=0,w[N],d[N],f[N],bin[N*2],b[N],g[N];char s[N];
inline void tarjan(int x){
    dfn[x]=low[x]=++DFN;b[x]=ID;w[x]=s[x]-'0';
    for(int i=head[x];i;i=nxt[i]){
        int u=to[i];
        if(!dfn[u]){
            tarjan(u);
            low[x]=min(low[x],low[u]);w[x]+=w[u];
            if(low[u]>=dfn[x])d[x]|=(w[u]&1),f[x]++,g[x]+=w[u];
        }
        else low[x]=min(low[x],dfn[u]);
    }
    if(x==ID)f[x]--;
}
inline void work(){
    int x,y;
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        gi(x);gi(y);in[x]++;in[y]++;
        link(x,y);link(y,x);
    }
    scanf("%s",s+1);
    int ans=m-n,c=0;
    for(int i=1;i<=n;i++)
        if(!dfn[i])ID=i,tarjan(i),ans++,c+=(w[i]&1);
   printf("%d",c?0:bin[ans]);
    for(int i=1;i<=n;i++){
        if(d[i])printf(" 0");
        else if(c-(w[b[i]]&1))printf(" 0");
        else if((w[b[i]]-(s[i]=='1')-g[i])&1)printf(" 0");
        else printf(" %d",bin[ans-in[i]+1+f[i]]);
    }
}
inline void Clear(){
    DFN=num=0;
    for(int i=0;i<N;i++)head[i]=dfn[i]=low[i]=f[i]=d[i]=in[i]=g[i]=0;
}
int main(){
  freopen("pp.in","r",stdin);
  freopen("pp.out","w",stdout);
  int T;cin>>T;
  bin[0]=1;for(int i=1;i<200005;i++)bin[i]=bin[i-1]*2%mod;
  while(T--)Clear(),work(),puts("");
  return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325075661&siteId=291194637