zoukankan      html  css  js  c++  java
  • 【BZOJ5303】【HAOI2018】—反色游戏(结论+tarjan割点)

    传送门

    出题人的题解:

    有个显然的结论,只有一个联通块中有偶数个节点才有解
    为什么呢?我们将黑点任意两两配对,对一对黑点考虑它们之间的任意一条路径,将路径上的边的状态(操作or不操作)取反,立即可以得到一种合法方案,

    那显然在一棵树上的方案数只有1种
    考虑一个联通块的非树边,显然是可以替换掉树上的一条路径的
    那非树边的选或不选就对应了不同的点集,则方案数就是2mn+12^{m-n+1}
    而对于一个图,方案数就是2mn+p,p2^{m-n+p},p是联通块个数

    那对于删去一个点就很简单了,考虑一下删去对所在联通块和黑点数目的影响分类讨论就可以了

    注意特判一个点的情况

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
    	return res*f;
    }
    const int N=100005;
    const int mod=1000000007;
    int n,m,adj[N],nxt[N<<1],to[N<<1],in[N<<1],pow2[N],cnt;
    int dfn[N],low[N],tot,cut[N],siz[N],vis[N],bel[N],belnum,sub[N];
    char s[N];
    inline void addedge(int u,int v){
    	nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
    }
    inline void clear(){
    	memset(adj,0,sizeof(adj));
    	memset(dfn,0,sizeof(dfn));
    	memset(siz,0,sizeof(siz));
    	memset(sub,0,sizeof(sub));
    	memset(cut,0,sizeof(cut));
    	memset(in,0,sizeof(in));
    	cnt=tot=0;
    }
    void tarjan(int u,int fa){
    	low[u]=dfn[u]=++tot;
    	vis[u]=1,siz[u]=s[u]=='1';
    	bel[u]=belnum;
    	for(int e=adj[u];e;e=nxt[e]){
    		int v=to[e];
    		if(!dfn[v]){
    			tarjan(v,u);
    			siz[u]+=siz[v];
    			if(low[v]>=dfn[u]){
    				++cut[u],vis[u]&=siz[v]%2==0;
    				sub[u]+=siz[v];
    			}
    			else low[u]=min(low[u],low[v]);
    		}
    		else if(v!=fa){
    			low[u]=min(low[u],dfn[v]);
    		}
    	}
    	if(!fa)--cut[u];
    }
    int main(){
    	pow2[0]=1;
    	for(int i=1;i<N;++i)pow2[i]=pow2[i-1]*2%mod;
    	int T=read();
    	while(T--){
    		n=read(),m=read();
    		clear();
    		for(int i=1;i<=m;++i){
    			int u=read(),v=read();
    			addedge(u,v),addedge(v,u);
    			++in[u],++in[v];
    		}
    		scanf("%s",s+1);
    		int num=0,odd=0;
    		for(int i=1;i<=n;++i){
    			if(!dfn[i]){
    				belnum=i,tarjan(i,0);
    				++num,odd+=siz[i]&1;
    			}
    		}
    		int ans=m-n+num;
    		cout<<((odd)?(0):(pow2[ans]));
    		for(int i=1;i<=n;++i){
    			if(!in[i])cout<<" "<<((odd==siz[i])?(pow2[ans]):(0));
    			else{
    				if(vis[i]&&((siz[bel[i]]-(s[i]=='1')-sub[i])%2==0)&&(odd==(siz[bel[i]]&1)))
    					cout<<" "<<(pow2[ans-in[i]+1+cut[i]]);
    				else cout<<" "<<0;
    			}
    		}
    		puts("");
    	}
    }
    
  • 相关阅读:
    聊聊 API Gateway 和 Netflix Zuul
    现行统编中学数学教科书有多烂
    线程池的成长之路
    Quick Guide to Microservices with Spring Boot 2.0, Eureka and Spring Cloud
    以太坊、Hyperledger Fabric和Corda,哪个更好?
    【SFA官方翻译】Spring WebFlux和Spring Cloud进行响应式微服务开发
    goroutine背后的系统知识
    goroutine与调度器
    MySQL命令,一篇文章替你全部搞定
    微服务架构技术栈选型手册(万字长文)
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145639.html
Copyright © 2011-2022 走看看