只需对每个联通块的$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 "); return 0; } } printf("TAK "); return 0; }