HDU - 5354 Bipartite Graph 分治 + 并查集 (看题解)
如果询问一个点的话, 直接用并查集check一下就好了。
要求n个点都求出答案的话, 用分治优化一下, 感觉挺巧妙的。
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define fio ios::sync_with_stdio(false); cin.tie(0); using namespace std; const int N = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; const double PI = acos(-1); template<class T, class S> inline void add(T &a, S b) {a += b; if(a >= mod) a -= mod;} template<class T, class S> inline void sub(T &a, S b) {a -= b; if(a < 0) a += mod;} template<class T, class S> inline bool chkmax(T &a, S b) {return a < b ? a = b, true : false;} template<class T, class S> inline bool chkmin(T &a, S b) {return a > b ? a = b, true : false;} mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); int n, m; vector<int> G[N]; int ans[N]; int fa[N], sz[N], xr[N]; int top; PII stk[N]; int txr[N]; PII getRoot(int x) { if(fa[x] == x) return mk(0, x); PII ret = getRoot(fa[x]); ret.fi ^= xr[x]; return ret; } bool unite(int u, int v) { PII x = getRoot(u); PII y = getRoot(v); if(x.se == y.se) { return (x.fi ^ y.fi); } else { if(sz[x.se] < sz[y.se]) swap(x, y); fa[y.se] = x.se; xr[y.se] = (x.fi ^ y.fi ^ 1); sz[x.se] += sz[y.se]; stk[++top] = mk(x.se, y.se); txr[top] = xr[y.se]; assert(top < N); return true; } } inline void rollback() { int x = stk[top].fi; int y = stk[top].se; xr[y] = txr[top]; top--; sz[x] -= sz[y]; fa[y] = y; } void init() { top = 0; for(int i = 1; i <= n; i++) { G[i].clear(); fa[i] = i; sz[i] = 1; xr[i] = 0; } } void solve(int l, int r) { if(l == r) { ans[l] = 1; return; } int preTop = top; int mid = l + r >> 1; bool can = true; for(int u = mid + 1; u <= r; u++) { for(auto &v : G[u]) { if(v >= l && v <= mid) continue; if(!unite(u, v)) { can = false; u = r + 1; break; } } } if(!can) { for(int u = l; u <= mid; u++) { ans[u] = 0; } } else { solve(l, mid); } while(top > preTop) rollback(); can = true; for(int u = l; u <= mid; u++) { for(auto &v : G[u]) { if(v > mid && v <= r) continue; if(!unite(u, v)) { can = false; u = r + 1; break; } } } if(!can) { for(int u = mid + 1; u <= r; u++) { ans[u] = 0; } } else { solve(mid + 1, r); } while(top > preTop) rollback(); } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d%d", &n, &m); init(); for(int i = 1; i <= m; i++) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } solve(1, n); for(int i = 1; i <= n; i++) { if(ans[i]) putchar('1'); else putchar('0'); } puts(""); } return 0; } /* */