1. 程式人生 > >bzoj4025 二分圖

bzoj4025 二分圖

alt lap isp oid online play src 復雜 bool

傳送門:http://www.lydsy.com/JudgeOnline/problem.php?id=4025

【題解】

考慮對時間分治,用可撤回的啟發式合並並查集來維護連通性。

二分圖的條件是沒有奇環,用並查集判即可。

對於時間區間[l,r],如果邊在這期間都存在,那麽就加入並查集,對於剩下的邊分類,並且分治下去做。

對於每條邊,在log個區間表示出來了,需要進行判斷,啟發式合並的getf是log的,所以復雜度為O(nlog^2n)

技術分享
# include <stdio.h>
# include <string.h>
# include <iostream>
# include 
<algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 5e5 + 10, N = 1e6 + 10; const int mod = 1e9+7; # define RG register # define ST static int n, m, T; struct edge { int u, v, st, ed; edge() {} edge(
int u, int v, int st, int ed) : u(u), v(v), st(st), ed(ed) {} }e[M]; int st[N]; int stn = 0; struct us { int n, fa[M], rk[M], dis[M]; inline void set(int _n) { n = _n; for (int i=1; i<=n; ++i) fa[i] = i, rk[i] = 1, dis[i] = 0; } inline int getf(int x) {
return fa[x] == x ? x : getf(fa[x]); } inline int getdis(int x) { int d = 0; while(fa[x] != x) d += dis[x], x = fa[x]; return d; } inline void un(int fu, int fv, int d) { if(rk[fu] > rk[fv]) swap(fu, fv); if(rk[fu] == rk[fv]) rk[fv] ++, st[++stn] = -fv; fa[fu] = fv; dis[fu] = d; ++stn; st[stn] = fu; } inline void re() { int x = st[stn]; --stn; if(x < 0) --rk[-x]; else dis[x] = 0, fa[x] = x; } }E; bool ans[M]; inline void solve(int tl, int tr, int er) { // printf("l = %d, r = %d\n", tl, tr); int cur_stn = stn; for (int i=1; i<=er; ++i) { if(!(e[i].st <= tl && tr <= e[i].ed)) continue; // printf("doing: (%d, %d, %d, %d)\n", e[i].u, e[i].v, e[i].st, e[i].ed); int fu = E.getf(e[i].u), fv = E.getf(e[i].v); int du = E.getdis(e[i].u), dv = E.getdis(e[i].v); if(fu != fv) E.un(fu, fv, du+dv+1); else { // printf("%d %d fa = %d %d %d\n", e[i].u, e[i].v, E.fa[1], du, dv); if((du+dv+1)&1) { // puts("Proves odd"); while(stn != cur_stn) E.re(); return ; } } swap(e[i], e[er]); --er; --i; } if(tl == tr) { ans[tl] = 1; while(stn != cur_stn) E.re(); return ; } int mid = tl+tr >> 1; int ER = er; for (int i=1; i<=er; ++i) if(e[i].st > mid) { swap(e[i], e[er]); --er; --i; } solve(tl, mid, er); er = ER; for (int i=1; i<=er; ++i) { if(e[i].ed <= mid) { swap(e[i], e[er]); --er; --i; } } solve(mid+1, tr, er); while(stn != cur_stn) E.re(); } int main() { cin >> n >> m >> T; E.set(n); int en = 0; for (int i=1, u, v, sta, end; i<=m; ++i) { scanf("%d%d%d%d", &u, &v, &sta, &end); ++sta; if(sta>end) continue; e[++en] = edge(u, v, sta, end); } m = en; solve(1, T, m); for (int i=1; i<=T; ++i) puts(ans[i] ? "Yes" : "No"); return 0; }
View Code

bzoj4025 二分圖