• BZOJ4025 : 二分图


    考虑离线。

    用Link-Cut Tree维护删除时间的最大生成树。

    加入一条边时,如果两点不连通则直接link,否则肯定有一条边多余,若形成奇环则将多余的边加入集合。

    删除一条边时,若这条边是树边则直接删除,否则若在集合中,则从集合中删除。

    查询时,如果集合中没有边,则为二分图。

    #include<cstdio>
    const int N=100010,M=200010,P=300010;
    int n,m,T,i,x,cnt;bool on[M],in[M];
    struct Edge{int x,y,z;}e[M];
    struct E{int v;E*nxt;}*ga[N],*gd[N],pool[M<<1],*cur=pool,*p;
    inline void adda(int x,int y){p=cur++;p->v=y;p->nxt=ga[x];ga[x]=p;}
    inline void addd(int x,int y){p=cur++;p->v=y;p->nxt=gd[x];gd[x]=p;}
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    int f[P],son[P][2],val[P],sum[P],mn[P],from[P],tmp[P];bool rev[P];
    inline void swap(int&a,int&b){int c=a;a=b;b=c;}
    inline bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;}
    inline void rev1(int x){if(!x)return;swap(son[x][0],son[x][1]);rev[x]^=1;}
    inline void pb(int x){if(rev[x])rev1(son[x][0]),rev1(son[x][1]),rev[x]=0;}
    inline void up(int x){
      mn[x]=val[x],from[x]=x,sum[x]=x>n;
      if(son[x][0]){
        if(mn[son[x][0]]<mn[x])mn[x]=mn[son[x][0]],from[x]=from[son[x][0]];
        sum[x]+=sum[son[x][0]];
      }
      if(son[x][1]){
        if(mn[son[x][1]]<mn[x])mn[x]=mn[son[x][1]],from[x]=from[son[x][1]];
        sum[x]+=sum[son[x][1]];
      }
    }
    inline void rotate(int x){
      int y=f[x],w=son[y][1]==x;
      son[y][w]=son[x][w^1];
      if(son[x][w^1])f[son[x][w^1]]=y;
      if(f[y]){
        int z=f[y];
        if(son[z][0]==y)son[z][0]=x;else if(son[z][1]==y)son[z][1]=x;
      }
      f[x]=f[y];f[y]=x;son[x][w^1]=y;up(y);
    }
    inline void splay(int x){
      int s=1,i=x,y;tmp[1]=i;
      while(!isroot(i))tmp[++s]=i=f[i];
      while(s)pb(tmp[s--]);
      while(!isroot(x)){
        y=f[x];
        if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
        rotate(x);
      }
      up(x);
    }
    inline void access(int x){for(int y=0;x;y=x,x=f[x])splay(x),son[x][1]=y,up(x);}
    inline void makeroot(int x){access(x);splay(x);rev1(x);}
    inline int root(int x){access(x);splay(x);while(son[x][0])x=son[x][0];return x;}
    inline void link(int x,int y){makeroot(x);f[x]=y;access(x);}
    inline void cutf(int x){access(x);splay(x);f[son[x][0]]=0;son[x][0]=0;up(x);}
    inline void cut(int x,int y){makeroot(x);cutf(y);}
    inline void add(int x){
      int u=e[x].x,v=e[x].y;
      if(u==v){in[x]=1,cnt++;return;}
      if(root(u)!=root(v))on[x]=1,link(u,x+n),link(v,x+n);
      else{
        makeroot(u);access(v);splay(v);
        int y=from[v]-n;
        if(e[y].z<e[x].z){
          if(sum[v]&1^1)in[y]=1,cnt++;
          cut(e[y].x,y+n),cut(e[y].y,y+n);
          link(u,x+n),link(v,x+n);
          on[y]=0,on[x]=1;
        }else if(sum[v]&1^1)in[x]=1,cnt++;
      }
    }
    inline void del(int x){if(on[x])cut(e[x].x,x+n),cut(e[x].y,x+n);else if(in[x])cnt--;}
    int main(){
      for(read(n),read(m),read(T);i<=n;i++)val[i]=mn[i]=1000000000,from[i]=i;
      for(i=1;i<=m;i++){
        read(e[i].x),read(e[i].y),read(x),read(e[i].z);
        adda(x,i),addd(e[i].z,i);
        val[i+n]=mn[i+n]=e[i].z,from[i+n]=i+n,sum[i+n]=1;
      }
      for(i=0;i<T;i++){
        for(p=ga[i];p;p=p->nxt)add(p->v);
        for(p=gd[i];p;p=p->nxt)del(p->v);
        puts(cnt?"No":"Yes");
      }
      return 0;
    }
    

      

  • 相关阅读:
    随时间的反向传播算法 BPTT
    实时绘制训练过程中损失和准确率的变化趋势 python keras jupyter notebook
    测试集的准确率为什么高于训练集的准确率?
    Adagrad和Stochastic梯度下降
    使用http-server在本地搭建一个HTTP服务器
    JS Promise
    npm淘宝镜像
    git子模块submodule
    git本地与远程分支
    git别名
  • 原文地址:https://www.cnblogs.com/clrs97/p/4709115.html
Copyright © 2020-2023  润新知