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

暴力做法是列异或方程组后高斯消元,答案为2^自由元个数,可以得60分。但这个算法已经到此为止了。

从图论的角度考虑这个问题,当原图是一棵树时,可以从叶子开始唯一确定每条边的选择情况,所以答案为1。

于是首先,对一个连通块,若其中黑点个数为奇数则必然无解,否则考虑求出它的一棵生成树。然后当我们选择一条非树边(u,v)时,只需要将树上u,v两点间的所有边的选取情况取反,就又得到一个合法方案。于是答案为$2^{m-n+1}$。进一步可以发现,设原图连通块个数为c,则答案为$2^{m-n+c}$。

现在考虑删去一个点后的改变:

若此点不是割点,则根据它的颜色更新有奇数个黑点的连通块个数,直接输出即可。

若此点是割点,那么还要考虑删去它后,被分割后的几个连通块中是否出现了有奇数个黑点的连通块。

那么,对于每个割点,我们需要计算(其中“之后”是指DFS序在i之后):w[i]这个点及之后的点中黑点的个数,d[i]删去这个点后之后的被分割出的连通块中是否存在有奇数个黑点的,f[i]删去这个点后会新增多少个连通块(对根特判)。最后分情况讨论无解即可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
 5 using namespace std;
 6 
 7 const int N=100010,mod=1e9+7;
 8 char ch;
 9 int T,n,m,u,v,s[N],w[N],b[N],dfn[N],low[N],f[N],d[N],ind[N],bin[N];
10 int cnt,ID,tim,ans,c,h[N],to[N<<1],nxt[N<<1];
11 
12 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
13 void init(){ cnt=tim=c=0; rep(i,1,n) dfn[i]=f[i]=d[i]=ind[i]=h[i]=0; }
14 
15 void Tarjan(int x){
16     b[x]=ID; dfn[x]=low[x]=++tim;
17     For(i,x) if (!dfn[k=to[i]]){
18         Tarjan(k); low[x]=min(low[x],low[k]); w[x]+=w[k];
19         if (low[k]>=dfn[x]) d[x]|=w[k]&1,f[x]++;
20     }else low[x]=min(low[x],dfn[k]);
21     if (x==ID) f[x]--;
22 }
23 
24 int main(){
25     freopen("game.in","r",stdin);
26     freopen("game.out","w",stdout);
27     bin[0]=1; rep(i,1,200000) bin[i]=(bin[i-1]<<1)%mod;
28     for (scanf("%d",&T); T--; ){
29         scanf("%d%d",&n,&m); init(); ans=m-n;
30         rep(i,1,m) scanf("%d%d",&u,&v),add(u,v),add(v,u),ind[u]++,ind[v]++;
31         rep(i,1,n) scanf(" %c",&ch),w[i]=s[i]=ch-'0';
32         rep(i,1,n) if (!dfn[i]) ID=i,Tarjan(i),ans++,c+=w[i]&1;
33         printf("%d ",c ? 0 : bin[ans]);
34         rep(i,1,n){
35             if (d[i]) printf("0 ");
36             else if (c-(w[b[i]]&1)) printf("0 ");
37                 else if ((w[b[i]]-s[i])&1) printf("0 ");
38                     else printf("%d ",bin[ans-ind[i]+1+f[i]]);
39         }
40         puts("");
41     }
42     return 0;
43 }

 

posted @ 2019-02-06 20:22  HocRiser  阅读(211)  评论(0编辑  收藏  举报