zoukankan      html  css  js  c++  java
  • 【LOJ】#2493. 「BJOI2018」染色

    题面

    题解

    推结论大题……然而我推不出什么结论

    奇环显然是NO

    如果一个联通块里有两个分离的环,也是NO

    如果一个联通块里,点数为n,边数为m
    m <= n的时候,是YES

    m >= n + 2的时候,肯定是NO

    m = n + 1的时候
    如果只存在一个双联通分量的话,取出这个双联通分量,存在两个点点度为3

    他们之间有3条路径,如果其中两条为2的话答案是YES,否则是NO

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define MAXN 20005
    #define eps 1e-8
    //#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);
    }
    struct node {
        int to,next;
    }E[MAXN * 2];
    int N,M,head[MAXN],sumE,col[MAXN];
    int dfn[MAXN],low[MAXN],idx,sta[MAXN],top,cnt,Ecnt,Ncnt,tot;
    int vis[MAXN],tims,deg[MAXN],path[5],pc;
    vector<int> ver[MAXN];
    void add(int u,int v) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    void Init() {
        read(N);read(M);
        sumE = 0;memset(head,0,sizeof(head));
        memset(col,0,sizeof(col));memset(vis,0,sizeof(vis));tims = 0;
        memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));idx = 0;
        int u,v;
        for(int i = 1 ; i <= M ; ++i) {
    	read(u);read(v);
    	add(u,v);add(v,u);
        }
    }
    bool color(int u) {
        if(!col[u]) col[u] = 2;
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(!col[v]) {
    	    col[v] = col[u] ^ 1;
    	    if(!color(v)) return false;
    	}
    	else if(col[v] == col[u]) return false;
        }
        return true;
    }
    void Tarjan(int u) {
        dfn[u] = low[u] = ++idx;
        sta[++top] = u;
        ++Ncnt;
        for(int i = head[u] ; i ; i = E[i].next) {
    	++Ecnt;
    	int v = E[i].to;
    	if(dfn[v]) {low[u] = min(low[u],dfn[v]);}
    	else {
    	    Tarjan(v);
    	    if(low[v] >= dfn[u]) {
    		int t = 1;
    		++tot;ver[tot].clear();ver[tot].pb(u);
    		while(1) {
    		    int x = sta[top--];
    		    ++t;
    		    ver[tot].pb(x);
    		    if(x == v) break;
    		}
    		if(t >= 4) ++cnt;
    	    }
    	    low[u] = min(low[u],low[v]);
    	}
        }
    }
    void dfs_path(int u,int fa,int ed,int dep) {
        if(u == ed) {path[++pc] = dep;return;}
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(vis[v] == tims && v != fa) {
    	    dfs_path(v,u,ed,dep + 1);
    	}
        }
    }
    void Solve() {
        for(int i = 1 ; i <= N ; ++i) {
    	if(!col[i]) {
    	    if(!color(i)) {puts("NO");return;}
    	}
        } 
        
        for(int i = 1 ; i <= N ; ++i) {
    	if(!dfn[i]) {
    	    top = 0;cnt = 0;Ecnt = 0;Ncnt = 0;tot = 0;
    	    Tarjan(i);
    	    Ecnt /= 2;
    	    if(Ecnt <= Ncnt) continue;
    	    if(Ecnt >= Ncnt + 2) {puts("NO");return;}
    	    if(cnt >= 2) {puts("NO");return;}
    	    ++tims;
    	    int st,ed;
    	    for(int j = 1 ; j <= tot;  ++j) {
    		if(ver[j].size() >= 4) {
    		    for(int k = 0 ; k < ver[j].size() ; ++k) {
    			vis[ver[j][k]] = tims;
    			deg[ver[j][k]] = 0;
    		    }
    		    for(int k = 0 ; k < ver[j].size() ; ++k) {
    			int u = ver[j][k];
    			for(int h = head[u] ; h ; h = E[h].next) {
    			    int v = E[h].to;
    			    if(vis[v] == tims) {
    				++deg[u];
    			    }
    			}
    		    }
    		    st = 0;ed = 0;
    		    for(int k = 0 ; k < ver[j].size() ; ++k) {
    			int u = ver[j][k];
    			if(deg[u] == 3) {
    			    if(!st) st = u;
    			    else if(!ed) ed = u; 
    			}
    		    }
    		    break;
    		}
    	    }
    	    pc = 0;
    	    dfs_path(st,0,ed,0);
    	    sort(path + 1,path + pc + 1);
    	    if(path[1] == 2 && path[2] == 2) continue;
    	    else {puts("NO");return;}
    	}
        }
        puts("YES");
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        int T;
        read(T);
        while(T--) {
    	Init();
    	Solve();
        }
        return 0;
    }
    
  • 相关阅读:
    真正的e时代
    在线手册
    UVA 10616 Divisible Group Sums
    UVA 10721 Bar Codes
    UVA 10205 Stack 'em Up
    UVA 10247 Complete Tree Labeling
    UVA 10081 Tight Words
    UVA 11125 Arrange Some Marbles
    UVA 10128 Queue
    UVA 10912 Simple Minded Hashing
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9984078.html
Copyright © 2011-2022 走看看