bipartite - LCT

题目大意:加边删边判定图是否是二分图。n<=1e5.
题解:还是维护最大删除时间生成树,当加入一条边形成奇环的时候,将换上删除时间最小的边断开,并截止这个时间之前都不会是二分图。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define mp make_pair
#define fir first
#define sec second
using namespace std;typedef pair<int,int> pii;const int N=200010,INF=1e9;
namespace INPUT_SPACE{
    const int BS=(1<<24)+5;char Buffer[BS],*HD,*TL;inline int gc() { if(HD==TL) TL=(HD=Buffer)+fread(Buffer,1,BS,stdin);return (HD==TL)?EOF:*HD++; }
    inline int inn() { int x,ch;while((ch=gc())<'0'||ch>'9');x=ch^'0';while((ch=gc())>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0');return x; }
}using INPUT_SPACE::inn;
struct MyHeap{
    priority_queue<int> q;MyHeap() { while(!q.empty()) q.pop(); }
    inline int insert(int x) { return q.push(x),0; }
    inline int empty(int x) { while(!q.empty()&&q.top()<=x) q.pop();return q.empty(); }
}hp;
struct E{
    int L,R,u,v,c;inline bool operator<(const E &e)const { return L<e.L; }
    E(int _L=0,int _R=0,int _u=0,int _v=0,int _c=0) { L=_L,R=_R,u=_u,v=_v,c=_c; }
}eg[N];map<pii,int> es;pii val[N],valp[N];
int fa[N],ch[N][2],sz[N],szp[N],pf[N],rev[N],del[N],pid[N],in[N];
inline int gw(int x) { return ch[fa[x]][1]==x; }
inline int push_up(int x) { return val[x]=min(valp[x],min(val[ch[x][0]],val[ch[x][1]])),sz[x]=szp[x]+sz[ch[x][0]]+sz[ch[x][1]]; }
inline int setc(int x,int y,int z) { if(!x) return fa[y]=0;ch[x][z]=y;if(y) fa[y]=x;return push_up(x); }
inline int rotate(int x) { int y=fa[x],z=fa[y],a=gw(x),b=gw(y),c=ch[x][a^1];return swap(pf[x],pf[y]),setc(y,c,a),setc(x,y,a^1),setc(z,x,b); }
inline int push_down(int x) { rep(i,0,1) if(ch[x][i]) ch[x][i][rev]^=1;return swap(ch[x][0],ch[x][1]),rev[x]=0; }
inline int all_down(int x) { return (fa[x]?all_down(fa[x]):0),(rev[x]?push_down(x):0); }
inline int splay(int x) { for(all_down(x);fa[x];rotate(x)) if(fa[fa[x]]) rotate(gw(x)==gw(fa[x])?fa[x]:x);return 0; }
inline int expose(int x) { splay(x);int y=ch[x][1];if(!y) return 0;return fa[y]=ch[x][1]=0,pf[y]=x,push_up(x); }
inline int splice(int x) { splay(x);int y=pf[x];if(!y) return 0;return expose(y),splay(y),setc(y,x,1),pf[x]=0,1; }
inline int access(int x) { expose(x);while(splice(x));return splay(x); }
inline int evert(int x) { return access(x),splay(x),rev[x]^=1; }
inline int link(int x,int y) { return evert(x),evert(y),splay(x),splay(y),pf[y]=x; }
inline int cut(int x,int y) { return evert(x),access(y),splay(x),ch[x][1]=fa[y]=0,push_up(x); }
inline int querysz(int x,int y) { return evert(x),access(y),splay(x),sz[x]; }
inline pii querymin(int x,int y) { return evert(x),access(y),splay(x),val[x]; }
inline int getr(int x) { while(fa[x]) x=fa[x];return x; }
inline int con(int x,int y) { evert(x),access(y),splay(x);int ans=(getr(y)==x);splay(y);return ans; }
char ss[100000*5];int ssl;
int main()
{
    int n=inn(),m=inn(),nc=n,cnt=0;
    rep(i,1,n) val[i]=valp[i]=mp(INF,0);val[0]=valp[0]=mp(INF,0);
    rep(i,1,m)
    {
        int u=inn(),v=inn();if(u>v) swap(u,v);
        if(!es[mp(u,v)]) es[mp(u,v)]=i;
        else eg[++cnt]=E(es[mp(u,v)],i,u,v,++nc),es[mp(u,v)]=0,del[i]=nc;
    }
    for(map<pii,int>::iterator it=es.begin();it!=es.end();it++)
        if(it->sec) eg[++cnt]=E(it->sec,m+1,it->fir.fir,it->fir.sec,++nc);
    sort(eg+1,eg+cnt+1);
    for(int i=1,j=1;i<=m;i++)
    {
        if(del[i]&&in[pid[del[i]]])
        {
            int p=pid[del[i]];in[p]=0;
            cut(eg[p].c,eg[p].u),cut(eg[p].c,eg[p].v);
        }
        for(;j<=cnt&&eg[j].L<=i;j++)
        {
            int u=eg[j].u,v=eg[j].v,c=eg[j].c;pid[c]=j;
            sz[c]=szp[c]=1,val[c]=valp[c]=mp(eg[j].R,c);
            if(!con(u,v)) link(u,c),link(c,v),in[j]=1;
            else{
                int p=pid[querymin(u,v).sec];
                if(!(querysz(u,v)&1)) hp.insert(min(eg[p].R,eg[j].R));
                if(eg[p].R<eg[j].R)
                    cut(eg[p].c,eg[p].u),cut(eg[p].c,eg[p].v),
                    link(c,u),link(c,v),in[j]=1,in[p]=0;
            }
        }
        if(hp.empty(i)) ss[++ssl]='Y',ss[++ssl]='E',ss[++ssl]='S',ss[++ssl]='\n';
        else ss[++ssl]='N',ss[++ssl]='O',ss[++ssl]='\n';
    }
    return fwrite(ss+1,sizeof(char),ssl,stdout),0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值