bzoj4025: 二分图

bzoj4025: 二分图


博主回归啦,懒得开小号了

神仙的一批。。。只会LCT,瑟瑟发抖

首先用LCT维护一棵树,把边加和删的时间点拿出来sort一遍就变成了加边和删边操作

如果要加进去一条边的时候发现这两点还没有联通就直接LCT上连边;要删的话如果在LCT上就在LCT上删边

如果发现这条边会构成奇环(后面叫它“奇环边”)就不是二分图了,把这条边单独放在一个地方存起来(set),要删的时候从那里删

每个时刻末尾,当没有奇环边的时候输出Yes,有就输出No

然后发现很麻烦不好处理,因为从LCT上删边之后,一些奇环边就不再是奇环边了,可以重新回到LCT,但这个很不好维护,所以要保证在LCT上删边的时候没有一条奇环边对它有影响

把边权设为这条边要删除的时间,维护最大生成树,每次要加新边的时候如果这两点已经联通就尝试消圈

如果一条边加入会构成奇环,这条边又通过消圈进入了LCT,要把消掉的那条边加入奇环集合

就能保证LCT上的边删除时奇环边集合不会对LCT有影响

然后代码异常丑陋:

#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il int gi(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
const int maxn=300100;
struct edge{int u,v,t,ed,o,id;}E[400100];
il bool operator <(const edge&a,const edge&b){
    if(a.t^b.t)return a.t<b.t;
    else return a.o==-1;
}
int ch[maxn][2],fa[maxn],siz[maxn],w[maxn],mn[maxn];bool rev[maxn];
int A[maxn],B[maxn];
il vd Rev(int x){if(x)std::swap(ch[x][0],ch[x][1]),rev[x]^=1;}
il bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
il vd upd(int x){
    if(x){
        siz[x]=1+siz[ch[x][0]]+siz[ch[x][1]];
        mn[x]=x;
        if(w[mn[ch[x][0]]]<w[mn[x]])mn[x]=mn[ch[x][0]];
        if(w[mn[ch[x][1]]]<w[mn[x]])mn[x]=mn[ch[x][1]];
    }
}
il vd down(int x){
    if(x==0)return;
    if(!isrt(x))down(fa[x]);
    if(rev[x])Rev(ch[x][0]),Rev(ch[x][1]),rev[x]=0;
}
il vd rotate(int x){
    int y=fa[x],z=fa[y],o=x==ch[y][1];
    fa[x]=z;if(!isrt(y))ch[z][y==ch[z][1]]=x;
    ch[y][o]=ch[x][!o];fa[ch[x][!o]]=y;
    fa[y]=x;ch[x][!o]=y;
    upd(y);
}
il vd splay(int x){
    if(x==0)return;
    down(x);
    for(int y=fa[x],z=fa[y];!isrt(x);rotate(x),y=fa[x],z=fa[y])
        if(!isrt(y))rotate(((x==ch[y][0])!=(y==ch[z][0]))?x:y);
    upd(x);
}
il vd access(int x){for(int y=0;x;x=fa[y=x])splay(x),ch[x][1]=y,upd(x);}
il vd makert(int x){access(x),splay(x),Rev(x);}
il vd link(int x,int y){
    makert(x);fa[x]=y;
}
il vd cut(int x,int y){
    makert(x),access(y),splay(y);ch[y][0]=fa[x]=0;
}
il std::pair<int,int> dist(int x,int y){
    makert(x),access(y),splay(y);
    int z=y;while(ch[z][0])z=ch[z][0];
    if(z!=x)return std::make_pair(-1,-1);
    else return std::make_pair(siz[y]-1,mn[y]);
}
std::set<int>edgeList;
bool yes[maxn];
int main(){
    int n=gi(),m=gi(),T=gi(),cnt=0;
    for(int i=1;i<=m;++i){
        int u=gi(),v=gi(),st=gi()+1,ed=gi()+1;
        if(st==ed)continue;
        E[++cnt]=(edge){u,v,st,ed,1,i};
        E[++cnt]=(edge){u,v,ed,ed,-1,i};
    }
    std::stable_sort(E+1,E+cnt+1);
    int p=1;
    for(int i=0;i<=n;++i)w[i]=1e9;
    for(int t=1;t<=T;++t){
        while(p<=cnt&&E[p].t<=t){
            if(E[p].o==-1){
                std::set<int>::iterator it=edgeList.find(E[p].id);
                if(it!=edgeList.end())edgeList.erase(it);
                else if(!yes[E[p].id])cut(E[p].u,n+E[p].id),cut(E[p].v,n+E[p].id);
            }else{
                std::pair<int,int> d=dist(E[p].u,E[p].v);
                if(E[p].u==E[p].v)edgeList.insert(E[p].id);
                else if(d.first==-1){
                    int x=E[p].id+n;
                    w[x]=E[p].ed;
                    link(A[x]=E[p].u,x),link(B[x]=E[p].v,x);
                }
                else if(w[d.second]<E[p].ed){
                    int x=n+E[p].id;
                    w[x]=E[p].ed;
                    cut(d.second,A[d.second]),cut(d.second,B[d.second]);
                    if(d.first%4==2)yes[d.second-n]=1;
                    else edgeList.insert(d.second-n);
                    A[x]=E[p].u,B[x]=E[p].v;
                    link(x,A[x]),link(x,B[x]);
                }
                else if(d.first%4==0)edgeList.insert(E[p].id);
                else yes[E[p].id]=1;
            }
            ++p;
        }
        if(edgeList.empty())puts("Yes");
        else puts("No");
    }
    return 0;
}
posted @ 2018-07-26 12:22  菜狗xzz  阅读(140)  评论(0编辑  收藏  举报