給你一張\(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 ...