题目大意:神犇有一个n个节点的图。因为神犇是神犇,所以在T时间内一些边会出现后消失。神犇要求出每一时间段内这个图是否是二分图。这么简单的问题神犇当然会做了,于是他想考考你
题解:联通且不含奇环,带权并查集+分治
ORZ Candy?
路径压缩的优化是均摊的,均摊在分治这种树形结构上使用是无效的
我的收获:orz
#include <bits/stdc++.h>
using namespace std;
const int N=100005;
int n,m,T;
int f[N],d[N],rk[N];
int top,stk[N<<1];
struct edge{
int u,v,sr,ez;
edge(){}
edge(int _,int __,int ___,int ____){u=_,v=__,sr=___,ez=____;}
int read(){scanf("%d%d%d%d",&u,&v,&sr,&ez);sr++;}
}temp;
vector<edge> G;
inline int Find(int x){
while(f[x]!=x) x=f[x];
return f[x]=x;
}
inline int Distance(int x){
int ret=0;
while(f[x]!=x&&f[x]) ret^=d[x],x=f[x];
return ret;
}
inline void Union(int x,int y,int z)
{
x=Find(x),y=Find(y);
if(x==y) return ;
if(rk[x]>rk[y]) swap(x,y);
if(rk[x]==rk[y]) rk[y]++,stk[++top]=-y;
f[x]=y,d[x]=z,stk[++top]=x;
}
inline void Restore(int bottom)
{
while(top>bottom)
{
if(stk[top]<0) rk[-stk[top]]--;
else f[stk[top]]=stk[top],d[stk[top]]=0;
top--;
}
}
void solve(int l,int r,vector<edge> &e)
{
int mid=l+r>>1,bottom=top;
vector<edge>ls,rs;
for(int i=0;i<e.size();i++)
{
edge now=e[i];
if(now.sr==l&&now.ez==r){
int x=Find(now.u),y=Find(now.v);
int z=Distance(now.u)^Distance(now.v)^1;
if(x!=y) Union(x,y,z);
else if(z&1)
{
for(int i=l;i<=r;i++) puts("No");
Restore(bottom);return;
}
}
else if(now.ez<=mid) ls.push_back(now);
else if(now.sr>mid) rs.push_back(now);
else{
ls.push_back(edge(now.u,now.v,now.sr,mid));
rs.push_back(edge(now.u,now.v,mid+1,now.ez));
}
}
if(l==r) puts("Yes");
else solve(l,mid,ls),solve(mid+1,r,rs);
Restore(bottom);
}
void work()
{
solve(1,T,G);
}
void init()
{
scanf("%d%d%d",&n,&m,&T);
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=m;i++) {
temp.read();
if(temp.sr>=temp.ez) continue;
G.push_back(temp);
}
}
int main()
{
init();
work();
return 0;
}