XSY2469 graph 分治 並查集

2022-03-25 18:09:09 字數 1603 閱讀 2644

給你一張\(n\)個點\(m\)條邊的無向圖,問刪去每個點後,原圖是不是二分圖。

\(n,m\leq 100000\)

乙個圖是二分圖\(\longleftrightarrow\)該圖不存在奇環

可以用並查集,維護每個點到根的距離

如果刪除\(x\)點,就要把所有不與\(x\)連線的邊加入並查集

考慮分治,對於區間\([l,r]\),我們先把與\([l,mid]\)鏈結且不與\([mid+1,r]\)鏈結的邊加入並查集,然後遞迴處理\([mid+1,r]\)。另一邊的情況類似。

因為有撤銷操作,所以要用按秩合併的並查集

時間複雜度:\(o(m\log^2 n)\)

#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

typedef pairpii;

struct list

void add(int x,int y) };

list li;

int f[100010];

int s[100010];

int d[100010];

int find(int x)

int getdist(int x)

int e1[100010];

int e2[100010];

int top;

int ans[100010];

int merge(int x,int y)

else

return 0;

}void solve(int l,int r)

int mid=(l+r)>>1;

int now=top;

int i,j;

int b=1;

for(i=l;i<=mid&&b;i++)

for(j=li.h[i];j&&b;j=li.t[j])

if(li.v[j]<=mid||li.v[j]>r)

b^=merge(i,li.v[j]);

if(b)

solve(mid+1,r);

else

for(i=mid+1;i<=r;i++)

ans[i]=0;

while(top>now)

now=top;

b=1;

for(i=mid+1;i<=r&&b;i++)

for(j=li.h[i];j&&b;j=li.t[j])

if(li.v[j]mid)

b^=merge(i,li.v[j]);

if(b)

solve(l,mid);

else

for(i=l;i<=mid;i++)

ans[i]=0;

while(top>now) }

void solve()

for(i=1;i<=n;i++)

solve(1,n);

for(i=1;i<=n;i++)

putchar(ans[i]+'0');

putchar('\n');

}int main()

XSY2423 跳蚤(根號分治)

神奇的分類討論。首先注意到每次所有跳蚤都只會往右跳,也就是說只要某乙隻跳蚤跳出了 max ri max r i max ri 它就不會再有貢獻了。和 火神的魚 類似 令 r max ri r max r i r max ri 考慮根號分治,將所有的跳蚤分成兩類 將 t i rt i sqrt ti ...

XSY2771 城市 分治

乙個平原上有 n 個城市,第 i 個城市在點 cos frac,sin frac 上。每個城市和最近的兩個城市有一條直線段的路。此外,還有 n 3 條路,這些路不會和原有的路重合,這些路之間也不會相交。通過每條道路均要花費 1 的時間。每次給你兩個城市,問你從乙個城市到另乙個城市最快要多久。n le...

XSY2423 跳蚤(根號分治)

神奇的分類討論。首先注意到每次所有跳蚤都只會往右跳,也就是說只要某乙隻跳蚤跳出了 max ri max r i max ri 它就不會再有貢獻了。和 火神的魚 類似 令 r max ri r max r i r max ri 考慮根號分治,將所有的跳蚤分成兩類 將 t i rt i sqrt ti ...