bzoj1116 [POI2008]CLO 边双联通分量

只需对每个联通块的$dfs$树检查有没有返租边即可

复杂度$O(n + m)$

#include <cstdio>
#include <cstring>
using namespace std;

extern inline char gc() {
    static char RR[23456], *S = RR + 23333, *T = RR + 23333;
    if(S == T) fread(RR, 1, 23333, stdin), S = RR;
    return *S ++;
}
inline int read() {
    int p = 0, w = 1; char c = gc();
    while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
    while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
    return p * w;
}

#define ri register int
#define sid 400050

int n, m, cnp, flag, id;
int dfn[sid], low[sid], cap[sid], node[sid], nxt[sid];

inline void addedge(int u, int v) {
    nxt[++ cnp] = cap[u]; cap[u] = cnp; node[cnp] = v;
}

void dfs(int o, int fa) {
    dfn[o] = low[o] = ++ id;
    #define cur node[i]
    for(int i = cap[o]; i; i = nxt[i]) {
        if(cur == fa) continue;
        if(!dfn[cur]) dfs(cur, o);
        else flag = 1;
    }
}

int main() {
    n = read(); m = read();
    for(ri i = 1; i <= m; i ++) {
        int u = read(), v = read();
        addedge(u, v); addedge(v, u);
    }
    for(ri i = 1; i <= n; i ++)
    if(!dfn[i]) {
        flag = 0; dfs(i, 0);
        if(!flag) { printf("NIE\n"); return 0; }
    }
    printf("TAK\n");
    return 0;
}

 

posted @ 2018-09-14 22:45  remoon  阅读(171)  评论(0编辑  收藏  举报