1. 程式人生 > >1116: [POI2008]CLO

1116: [POI2008]CLO

esp 聯通塊 pan col digi urn 就是 puts name

1116: [POI2008]CLO

https://lydsy.com/JudgeOnline/problem.php?id=1116

分析:

  單獨考慮每個聯通塊的情況。
  設這個聯通塊裏有n個點,那麽至少有n-1條邊了。
  如果每個點入度都為1,那麽就要求至少有n條邊(其實就是基環樹),大於n條邊可以不選。
  所以有:如果一個聯通塊是可行的,必須滿足存在大於等於點數條邊。
  所以並查集維護加邊的過程。
    1、出現了環,那麽這個聯通塊就合法了。
    2、合並兩個聯通塊,只要一個聯通塊裏合法就行。(一個合法了,另一個也至少存在n-1條邊,那麽加入這條後,剛好滿足了)。
代碼:

 1
#include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 #include<cctype> 7 #include<set> 8 #include<queue> 9 #include<vector> 10 #include<map> 11 using namespace std; 12 typedef long
long LL; 13 14 inline int read() { 15 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch==-)f=-1; 16 for(;isdigit(ch);ch=getchar())x=x*10+ch-0;return x*f; 17 } 18 19 const int N = 200005; 20 21 int fa[N], g[N]; 22 23 int find(int x) { 24 return x == fa[x] ? x : fa[x] = find(fa[x]);
25 } 26 27 int main() { 28 int n = read(), m = read(); 29 for (int i = 1; i <= n; ++i) fa[i] = i; 30 while (m --) { 31 int u = read(), v = read(); 32 u = find(u), v = find(v); 33 if (u == v) g[u] = 1; 34 else fa[u] = v, g[v] |= g[u]; 35 } 36 for (int i = 1; i <= n; ++i) 37 if (!g[find(i)]) return puts("NIE"), 0; 38 puts("TAK"); 39 return 0; 40 } 41

1116: [POI2008]CLO