zoukankan      html  css  js  c++  java
  • 【LOJ】#2524. 「HAOI2018」反色游戏

    题解

    如果一个联通块是一个树的话,方案数就一种,如果这个联通块还有别的边,那选了一条别的边就会把树上对应路径全部取反,所以方案数是(2^{m - n + 1})
    如果联通块数为(c)方案数为(2^{m - m + c})
    一个联通块有奇数个黑点一定为0

    然后就对于每个点判断是不是割点,是的话看看分成的联通块有几个包含奇数个黑点

    然后如果不是割点看看删掉这个点后联通块黑点个数的奇偶性改没改变

    同时要特判联通块里只有一个点的情况

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define pdi pair<db,int>
    #define mp make_pair
    #define pb push_back
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define eps 1e-8
    #define MAXN 100005
    #define mo 974711
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 + c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    const int MOD = 1000000007;
    int N,M,pw[200005];
    char s[MAXN];
    struct node {
        int to,next;
    }E[MAXN * 2];
    int head[MAXN],sumE,conn,deg[MAXN],rec[MAXN],incodd[MAXN],incconn[MAXN];
    int dfn[MAXN],low[MAXN],idx,sta[MAXN],top,siz[MAXN],black,odd;
    bool cut[MAXN],vis[MAXN],acs[MAXN];
    void add(int u,int v) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    int inc(int a,int b) {
        return a + b >= MOD ? a + b - MOD : a + b;
    }
    int mul(int a,int b) {
        return 1LL * a * b % MOD;
    }
    void Tarjan(int u,int fa) {
        int son = 0;
        low[u] = dfn[u] = ++idx;
        sta[++top] = u;
        siz[u] = (s[u] == '1');
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa) {
    	    if(dfn[v]) low[u] = min(low[u],dfn[v]);
    	    else {
    		Tarjan(v,u);
    		if(low[v] >= dfn[u]) {
    		    ++son;
    		    if(fa) cut[u] = 1;
    		    int t = 0;
    		    while(1) {
    			int x = sta[top--];
    			t += siz[x];
    			if(x == v) break;
    		    }
    		    incodd[u] += (t & 1);
    		    incconn[u]++;
    		    siz[u] += t;
    		}
    		low[u] = min(low[v],low[u]);
    	    }
    	}
        }
        if(!fa && son > 1) cut[u] = 1;
        if(cut[u]) {
    	if(fa) incconn[u]++;
    	incodd[u] += (black - siz[u] & 1);
    	if(odd - (black & 1) + incodd[u] == 0) acs[u] = 1;
        }
        else {
    	if(odd - (black & 1) + (black - (s[u] == '1') & 1) == 0) acs[u] = 1;
    	
        }
    }
    void dfs(int u) {
        vis[u] = 1;
        if(s[u] == '1') ++black;
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(!vis[v]) dfs(v);
        }
    }
    void Init() {
        read(N);read(M);
        memset(head,0,sizeof(head));sumE = 0;
        memset(deg,0,sizeof(deg));
        idx = 0;top = 0;conn = 0;
        memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));
        memset(siz,0,sizeof(siz));
        memset(cut,0,sizeof(cut));memset(vis,0,sizeof(vis));
        memset(acs,0,sizeof(acs));
        memset(incodd,0,sizeof(incodd));memset(incconn,0,sizeof(incconn));
        int u,v;
        for(int i = 1 ; i <= M ; ++i) {
    	read(u);read(v);
    	add(u,v);add(v,u);
    	deg[u]++;deg[v]++;
        }
        scanf("%s",s + 1);
        odd = 0;
        for(int i = 1 ; i <= N ; ++i) {
    	if(!vis[i]) {
    	    black = 0;
    	    ++conn;
    	    dfs(i);
    	    rec[i] = black;
    	    if(black & 1)++odd;
    	}
        }
    }
    void Solve() {
        if(odd >= 2) {
    	for(int i = 1 ; i <= N + 1 ; ++i) {out(0);space;}
    	return;
        }
        for(int i = 1 ; i <= N ; ++i) {
    	if(!dfn[i]) {
    	    top = 0;idx = 0;
    	    black = rec[i];
    	    Tarjan(i,0);
    	    if(!deg[i]) cut[i] = 1;
    	}
        }
        if(odd == 0) {
    	out(pw[M - N + conn]);space;
        }
        else {
    	out(0);space;
        }
        for(int i = 1 ; i <= N ; ++i) {
    	if(!acs[i]) out(0);
    	else if(cut[i]) {
    	    out(pw[(M - deg[i]) - (N - 1) - 1 + conn + incconn[i]]);
    	}
    	else {
    	    out(pw[(M - deg[i]) - (N - 1) + conn]);
    	}
    	space;
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        pw[0] = 1;
        for(int i = 1 ; i <= 200000; ++i) {
    	pw[i] = mul(pw[i - 1],2);
        }
        int T;
        read(T);
        while(T--) {Init();Solve();enter;}
    }
    
  • 相关阅读:
    CF1202F You Are Given Some Letters...
    CF1178E Archaeology
    PTA (Advanced Level) 1005 Spell It Right
    PTA (Advanced Level) 1004 Counting Leaves
    Qt5——从零开始的Hello World教程(Qt Creator)
    PTA (Advanced Level) 1003 Emergency
    PTA (Advanced Level) 1002 A+B for Polynomials
    HDU 1272 小希的迷宫
    FZU 2150 Fire Game
    HihoCoder
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10031785.html
Copyright © 2011-2022 走看看