「JOISC 2020 Day2」變戀龍之色 題解
阿新 • • 發佈:2021-06-23
注意
同性必定不同色
必有一個同色異性,且不相互不喜歡
Solution
我們發現,我們問題比較大的就是如何確定性別問題。我們可以一個一個加進去,在原來已經確定了的二分圖上增加新的性別關係,這個可以用線段樹上二分找到。
設找到的集合為 \(S\),元素為 \(S_0,S_1,...\),那麼你可以發現 \(|S|\) 只有兩種情況。
- \(|S|=1\)
這種時候說明 \(L_{L_x}=x\),所以 \(S_0\) 就是與 \(x\) 同色的。
- \(|S|=3\)
這個時候 \(S_0,S_1,S_2\) 就是喜歡 \(x\),被 \(x\) 喜歡的,以及與 \(x\) 同色的異性的。找到與 \(x\)
Code
#include "chameleon.h" #include<bits/stdc++.h> using namespace std; #define Int register int #define MAXN 1005 template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;} template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);} template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} template <typename T> inline void chkmax (T &x,T y){x = max (x,y);} template <typename T> inline void chkmin (T &x,T y){x = min (x,y);} vector <int> G[MAXN]; bool b[MAXN],used[MAXN]; int n,t[2][MAXN],col[MAXN],lov[MAXN],siz[2]; void dfs (int x,int c){ col[x] = c; for (Int to : G[x]) if (col[to] == -1) dfs (to,c ^ 1); } void getcol (int x){ for (Int i = 1;i < x;++ i) col[i] = -1; for (Int i = 1;i < x;++ i) if (col[i] == -1) dfs (i,0); siz[0] = siz[1] = 0; for (Int i = 1;i < x;++ i) t[col[i]][++ siz[col[i]]] = i; } bool checkit (int c,int l,int r,int x){ vector <int> S;S.clear (),S.push_back (x); for (Int i = l;i <= r;++ i) if (!b[t[c][i]]) S.push_back (t[c][i]); return Query (S) < S.size(); } int findit (int c,int l,int r,int x){ if (l == r) return t[c][l]; int mid = (l + r) >> 1; return checkit (c,l,mid,x) ? findit (c,l,mid,x) : findit (c,mid + 1,r,x); } void makeit (int Sn){ int n = Sn << 1; for (Int i = 1;i <= n;++ i){ getcol (i),memset (b,0,sizeof (b)); for (Int c = 0;c < 2;++ c){ while (checkit (c,1,siz[c],i)){ int pos = findit (c,1,siz[c],i); G[i].push_back (pos),G[pos].push_back (i),b[pos] = 1; } } } vector <int> S;S.resize (3); for (Int i = 1;i <= n;++ i){ if (G[i].size() == 1){ if (used[i]) continue; used[i] = used[G[i][0]] = 1,Answer (i,G[i][0]); continue; } S[0] = i,S[1] = G[i][0],S[2] = G[i][1]; if (Query (S) == 1){ swap (G[i][0],G[i][2]),lov[G[i][0]] = i; continue; } S[2] = G[i][2]; if (Query (S) == 1){ swap (G[i][0],G[i][1]),lov[G[i][0]] = i; continue; } lov[G[i][0]] = i; } for (Int i = 1;i <= n;++ i) if (!used[i]){ if (lov[i] == G[i][1]) Answer (i,G[i][2]),used[i] = used[G[i][2]] = 1; else Answer (i,G[i][1]),used[i] = used[G[i][1]] = 1; } } void Solve (int N){ makeit (N); }