[HAOI2018] Reverse color game

 

    The practice is very good, and the details are adjusted for a lifetime. It is estimated that this sentence is the most suitable for this question hhhh.

    The first is an obvious idea: set the edge as an unknown number, and set the XOR equation for the points, and the final number of solutions is 2^ free elements. 

    However, if there are an odd number of black dots in a connected component, then the problem is unsolved. Then let me prove it:

        XOR the equations represented by all points in a connected component, because the edge in this connected component is exactly 1 at its two endpoints, so the first m columns of the last XORed equation are all 0, if there are odd numbers If there is a black dot, the last column is 1, so there is no solution (can't be 0=1, hhh).

     The direct Gaussian elimination is O(N^3), and it must be gg (but it gave 60 points for elimination hhh, the person who asked the question is too conscientious).

 

    However, in general, if we eliminate (shou) yuan (wan) in a specific order, we will get some very conscientious conclusions (for details, please refer to bzoj's literary calculation Ji).

    Consider the two endpoints u, v of edge 1, because there can only be one row corresponding to 1 in this column at the end, so we turn the vth row into the uth row XOR the vth row, and you can find the meaning of the new row obtained Yes: the new point after the u point and the v point are merged (because the edge 1 is eliminated, there is no self-loop corresponding to a point).

    Of course, if we consider edge i and find that its two endpoints are already in a connected component, then this edge is a free element, because we can't find the i-th column in the Gaussian elimination matrix now. 1's OK.

    If we extend the above method, we can get a method that can calculate the global answer: the initial answer is 1, and the set is checked to maintain connectivity. If the attempt to merge fails, the answer is *2.

 

    But that's not great enough, because this question requires an answer with every dot removed.

    However, the above method is still a bit redundant, because if we think about its process carefully, we can find that the answer is actually 2^(mn + the number of Unicom components).

 

    Therefore, the biggest problem left now is: how to maintain, after deleting a point, the black dots of a certain connected component that may be brought become odd (corresponding to no solution) and the change of the number of connected components ( the connectivity of the corresponding graph)? ? ?

     

    Just run a tarjan algorithm to find the cut point. The first problem is a bit complicated. Let's solve the second problem first.

     

    The second question can be divided into the following situations:

        1. The deleted node is an isolated vertex: In this case, the number of connected components in the graph will be -1.

        2. Delete a cut point: This situation can be counted in tarjan, but if this point is the root of the dfs tree, the answer will be -1 (because there is no new connection component above)

        3. Delete a non-isolated vertex and non-cut point: no effect hhhh.

    But don't forget that deleting a point will not only affect the number of connected components, but also affect the total number of edges - the number of points in the graph.

 

    As for the first problem, we can deal with it in tarjan: after deleting a point, the change in the number of connected components with odd black points in the figure is derta[i].

    How to deal with it?   

    First, if this point is a cut point:

        1. If the connected component of this point has an odd number of black dots, let derta[i]-- first, because deleting this point will destroy the connected component.

        2. After adding and deleting this point to derta[i], the number of connected components with an odd number of black points cannot be returned to the ancestor in the dfs tree.

        3. If the connected component where the root of the dfs tree is located also has an odd number of black points after deleting this point, then derta[i]++.

    If the point i is a non-cut point and a non-isolated vertex, then derta[i] = color[i] == 1 ? (color[this tree] == 1 ? -1 : 1) : 0 .

    If this point is an isolated vertex, then derta[i] = color[i] == 1 ? -1 : 0.

 

    (Huh... I finally finished writing and I'm exhausted...)

 

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=200005,ha=1000000007;
inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;}
int to[maxn*2],ne[maxn*2],hd[maxn],num,n,m,T,ans,Sub[maxn];
int Xor[maxn],NewC[maxn],NewB[maxn],BC,ci[maxn];
int dfn[maxn],low[maxn],dc,tp,st[maxn],D[maxn];
bool iscut[maxn];
char S[maxn];
inline void addline(int x,int y){ to[++num]=y,ne[num]=hd[x],hd[x]=num,D[x]++;}
inline void init(){
	memset(hd,0,sizeof(hd)),num=0;
	memset(NewB,0,sizeof(NewB));
	memset(NewC,0,sizeof(NewC));
	memset(D,0,sizeof(D));
	memset(iscut,0,sizeof(iscut));
	memset(dfn,0,sizeof(dfn));
	memset(Sub,0,sizeof(Sub));
	dc=BC=0;
}
inline int read(){
	int x=0; char ch=getchar();
	for(;!isdigit(ch);ch=getchar());
	for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
	return x;
}
void W(int x){ if(x>=10) W(x/10); putchar(x%10+'0');}

void dfs(int x,int fa){
	st[++tp]=x,dfn[x]=low[x]=++dc;
	int cd=0; Sub[x]=Xor[x];
	for(int i=hd[x];i;i=ne[i]) if(to[i]!=fa)
	    if(!dfn[to[i]]){
	    	cd++,dfs(to[i],x);
			Xor[x]^=Xor[to[i]];
			low[x]=min(low[x],low[to[i]]);
			
	    	if(low[to[i]]>=dfn[x]){
	    		Sub[x]^=Xor[to[i]];
			    iscut[x]=1,NewC[x]++;
			    if(Xor[to[i]]) NewB[x]++;
			}
		}
		else low[x]=min(low[x],dfn[to[i]]);
	
	if(cd==1&&fa<0) iscut[x]=NewB[x]=NewC[x]=0;
	else if(fa<0) NewC[x]--;
}

inline void solve(){
	for(int i=1;i<=n;i++) if(S[i]=='1') Xor[i]=1; else Xor[i]=0;
	ans=m-n;
	for(int i=1;i<=n;i++) if(!dfn[i]){
		ans++;
		dfs(i,-1);
		if(Xor[i]) BC++;
		if(!hd[i]) NewC[i]=-1;
		
		for(;tp;tp--) if(iscut[st[tp]]){
			if(Xor[i]^Sub[st[tp]]) NewB[st[tp]]++;
			if(Xor[i]==1) NewB[st[tp]]--;
		}
		else NewB[st[tp]]=S[st[tp]]=='1'?(Xor[i]?-1:1):0;
	}
	
	if(BC) W(0); else W(ci[ans]); putchar(' ');
	for(int i=1;i<=n;i++){
		BC+=NewB[i],ans+=NewC[i]-D[i]+1;
		if(!BC) W(ci[ans]); else W(0); putchar(' ');
		BC-=NewB[i],ans-=NewC[i]-D[i]+1;
	}	
	puts("");
}

int main(){
	ci[0]=1; for(int i=1;i<=200000;i++) ci[i]=add(ci[i-1],ci[i-1]);
	T=read();
	while(T--){
		int uu,vv;
		init(),n=read(),m=read();
		for(int i=1;i<=m;i++) uu=read(),vv=read(),addline(uu,vv),addline(vv,uu);
		scanf("%s",S+1),solve();
	}
	return 0;
}

  

Guess you like

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