zoukankan      html  css  js  c++  java
  • 「HAOI2018」反色游戏(找性质+tarjan求割点)

    https://loj.ac/problem/2524

    类似于NOI ONline T1,
    对于一棵树,不难发现,当黑点个数为奇数时,一定无解,为偶数时,一定可以调整出唯一一组解。

    如果额外加一些非树边,那么不管非树边怎么选,树边都有办法调整,所以方案数是(2^{非树边数})

    考虑删掉一个点时,也就是看删掉这个点之后新形成的联通块有多少个,有没有联通块有奇数个黑点。

    如果知道tarjan求割点的方法,不难得到以下解法:

    对于一个联通块,随便选一个点作为根开始tarjan。

    对于根,如果删掉它,它的dfs树上的每个子树会形成一个联通块。

    对于dfs树上非根的点(x),如果删掉它,那些(low[y]ge dfn[x])的子节点(y)的子树会形成一个联通块,然后剩下的所有点会形成一个联通块。

    这样我们只要tarjan一遍,顺便维护一些信息(子树黑点个数,会独立的子树的信息),就可以得到答案了。

    Code:

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    const int mo = 1e9 + 7;
    
    ll ksm(ll x, ll y) {
    	ll s = 1;
    	for(; y; y /= 2, x = x * x % mo)
    		if(y & 1) s = s * x % mo;
    	return s;
    }
    
    const int N = 2e5 + 5;
    
    int T;
    
    int n, m, x, y, r[N];
    int fi[N], to[N * 2], nt[N * 2], tot = 1;
    char str[N]; int a[N];
    
    void link(int x, int y) {
    	nt[++ tot] = fi[x], to[tot] = y, fi[x] = tot;
    }
    
    int low[N], dfn[N], dfn0;
    
    void cl() {
    	fo(i, 1, n) r[i] = fi[i] = low[i] = dfn[i] = 0;
    	tot = 1;
    }
    
    int s[N], cnt[N][2], bz[N], G;
    
    void dg(int x, int la) {
    	bz[x] = G;
    	low[x] = dfn[x] = ++ dfn0;
    	s[x] = a[x];
    	cnt[x][0] = cnt[x][1] = 0;
    	for(int i = fi[x]; i; i = nt[i]) if(i != la) {
    		int y = to[i];
    		if(!dfn[y]) {
    			dg(y, i ^ 1);
    			s[x] ^= s[y];
    			low[x] = min(low[x], low[y]);
    			if(low[y] >= dfn[x]) {
    				cnt[x][s[y]] ++;
    			}
    		} else low[x] = min(low[x], dfn[y]);
    	}
    }
    
    int ltk;
    
    void work() {
    	scanf("%d %d", &n, &m);
    	fo(i, 1, m) {
    		scanf("%d %d", &x, &y);
    		link(x, y); link(y, x);
    		r[x] ++, r[y] ++;
    	}
    	scanf("%s", str + 1);
    	fo(i, 1, n) a[i] = str[i] - '0';
    	ltk = 0;
    	fo(i, 1, n) if(!dfn[i]) {
    		ltk ++;
    		G = i, dg(i, 0);
    	}
    }
    
    int main() {
    	scanf("%d", &T);
    	fo(ii, 1, T) {
    		cl();
    		work();
    		int c1 = 0;
    		fo(i, 1, n) if(bz[i] == i)
    			c1 += (s[i] == 1);
    		int c = m - n + ltk;
    		pp("%lld ", c1 > 0 ? 0 : ksm(2, c));
    		fo(i, 1, n) {
    			if(!r[i]) {
    				pp("%lld ", c1 > 0 ? 0 : ksm(2, c));
    			} else {
    				if(!cnt[i][1] && (c1 - s[bz[i]]) == 0 && (s[bz[i]] ^ a[i]) == 0) {
    					pp("%lld ", ksm(2, c - r[i] + 1 + cnt[i][0] - (bz[i] == i)));
    				} else pp("0 ");
    			}
    		}
    		hh;
    	}
    }
    
  • 相关阅读:
    mysql 性能优化方案1
    微信接口php
    IT girl
    jsonp 使用总结
    Oracle 10g体系机构及安全管理《思维导图》
    图形化报表
    JQuery中Ajax应用
    jquery中的事件与动画
    jquery的DOM操作
    jQuery中的选择器《思维导图》
  • 原文地址:https://www.cnblogs.com/coldchair/p/12719130.html
Copyright © 2011-2022 走看看