zoukankan      html  css  js  c++  java
  • 【BZOJ4025】二分图

    Description

    神犇有一个n个节点的图。由于神犇是神犇,所以在T时间内一些边会出现后消失。神犇要求出每一时间段内这个图是否是二分图。这么简单的问题神犇当然会做了,于是他想考考你。


    Input

    输入数据的第一行是三个整数n,m,T。
    第2行到第m+1行。每行4个整数u,v,start,end。

    第i+1行的四个整数表示第i条边连接u,v两个点。这条边在start时刻出现。在第end时刻消失。
    Output

    输出包括T行。

    在第i行中。假设第i时间段内这个图是二分图。那么输出“Yes”。否则输出“No”,不含引號。
    Sample Input

    3 3 3

    1 2 0 2

    2 3 0 3

    1 3 1 2
    Sample Output

    Yes

    No

    Yes
    HINT

    例子说明:

    0时刻,出现两条边1-2和2-3。

    第1时间段内,这个图是二分图,输出Yes。

    1时刻。出现一条边1-3。

    第2时间段内,这个图不是二分图,输出No。

    2时刻,1-2和1-3两条边消失。

    第3时间段内,仅仅有一条边2-3,这个图是二分图,输出Yes。

    数据范围:

    n<=100000,m<=200000,T<=100000,1<=u,v<=n。0<=start<=end<=T。

    Source

    能够考虑用LCT维护一个以删除时间为关键字的最大生成树
    同一时候维护一个边的集合表示在这个集合中的边假设在图中则一定不是二分图(就用一个数组就好了_ (:зゝ∠) _)
    由二分图的定义可知 二分图是没有奇环的图
    然后对于那两种操作:
    对于插入,假设边的两端点不连通,连边后一定不会形成环,直接link上
    假设已经联通,加边后一定存在非树边.此时假设加边后会形成奇环,就把这条边增加上述集合
    删除时候对于树边直接删除,非树边在集合中则直接从集合中删除

    事实上也能够用cdq+并查集来搞
    详细做法没考虑过可是能够看Po姐姐的Blog
    PoPoQQQ

    P.S.颓了那么久最终開始干正事了..

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define MAXN 100010
    #define GET (ch>='0'&&ch<='9')
    #define MAXINT 0x3f3f3f3f
    using namespace std;
    int n,m,T,Top,cnt;
    int sta[MAXN<<1],top;
    int In[MAXN<<1],on[MAXN<<1];
    struct splay
    {
        int ch[2],fa,minn,st,sum,val;
        bool rev;
    }tree[MAXN<<2];
    inline void in(int &x)
    {
        char ch=getchar();x=0;
        while (!GET)    ch=getchar();
        while (GET) x=x*10+ch-'0',ch=getchar();
    }
    struct edge
    {
        int u,v,w;
    }e[MAXN<<1];
    struct Edge
    {
        int to;
        Edge *next;
    }E[MAXN<<2],*prev1[MAXN],*prev2[MAXN];
    inline void insert1(int u,int v)    {E[++Top].to=v;E[Top].next=prev1[u];prev1[u]=&E[Top];}
    inline void insert2(int u,int v)    {E[++Top].to=v;E[Top].next=prev2[u];prev2[u]=&E[Top];}
    inline bool is_root(int x)
    {
        return tree[tree[x].fa].ch[0]!=x&&tree[tree[x].fa].ch[1]!=x;
    }
    inline void push_down(int x)
    {
        if (tree[x].rev)
        {
            tree[tree[x].ch[0]].rev^=1,tree[tree[x].ch[1]].rev^=1;
            swap(tree[x].ch[0],tree[x].ch[1]);
        }
        tree[x].rev=0;
    }
    inline void push_up(int x)
    {
        tree[x].minn=tree[x].val;tree[x].st=x;tree[x].sum=x>n;
        if (tree[x].ch[0])
        {
            if (tree[tree[x].ch[0]].minn<tree[x].minn)  tree[x].minn=tree[tree[x].ch[0]].minn,tree[x].st=tree[tree[x].ch[0]].st;
            tree[x].sum+=tree[tree[x].ch[0]].sum;
        }
        if (tree[x].ch[1])
        {
            if (tree[tree[x].ch[1]].minn<tree[x].minn)  tree[x].minn=tree[tree[x].ch[1]].minn,tree[x].st=tree[tree[x].ch[1]].st;
            tree[x].sum+=tree[tree[x].ch[1]].sum;
        }
    }
    inline void rot(int x)
    {
        int y=tree[x].fa,z=tree[y].fa,l,r;
        l=(tree[y].ch[1]==x);r=l^1;
        if (!is_root(y))    tree[z].ch[tree[z].ch[1]==y]=x;
        tree[tree[x].ch[r]].fa=y;tree[y].fa=x;tree[x].fa=z;
        tree[y].ch[l]=tree[x].ch[r];tree[x].ch[r]=y;
        push_up(y);push_up(x);
    }
    inline void Splay(int x)
    {
        top=0;sta[++top]=x;
        for (int i=x;!is_root(i);i=tree[i].fa)  sta[++top]=tree[i].fa;
        while (top) push_down(sta[top--]);
        while (!is_root(x))
        {
            int y=tree[x].fa,z=tree[y].fa;
            if (!is_root(y))
            {
                if ((tree[y].ch[0]==x)^(tree[z].ch[0]==y))  rot(x);
                else    rot(y);
            }
            rot(x);
        }
    }
    inline void access(int x)
    {
        for (int i=0;x;i=x,x=tree[x].fa)    Splay(x),tree[x].ch[1]=i,push_up(x);
    }
    inline void make_root(int x)
    {
        access(x);Splay(x);tree[x].rev^=1;
    }
    inline void link(int x,int y)
    {
        make_root(x);tree[x].fa=y;
    }
    inline void cut(int x,int y)
    {
        make_root(x);access(y);Splay(y);tree[y].ch[0]=tree[x].fa=0;push_up(y);
    }
    inline void split(int x,int y)
    {
        make_root(x);access(y);Splay(y);
    }
    inline int find_root(int x)
    {
        /*access(x);Splay(x);
        while (tree[x].ch[0])   x=tree[x].ch[0];*/
        for (access(x),Splay(x);tree[x].ch[0];x=tree[x].ch[0]);
        return x;
    }
    inline void ins(int x)
    {
        int u=e[x].u,v=e[x].v;
        if (u==v)   {In[x]=1;cnt++;return;}
        if (find_root(u)!=find_root(v)) on[x]=1,link(u,x+n),link(v,x+n);
        else
        {
            split(u,v);int y=tree[v].st-n;
            if (e[y].w<e[x].w)
            {
                if (tree[v].sum&1^1)    In[y]=1,cnt++;
                cut(e[y].u,y+n);cut(e[y].v,y+n);link(u,x+n);link(v,x+n);
                on[y]=0;on[x]=1;
            }
            else
            if (tree[v].sum&1^1)    In[x]=1,cnt++;
        }
    }
    inline void del(int x)
    {
        if (on[x])  cut(e[x].u,x+n),cut(e[x].v,x+n);
        else    if (In[x])  cnt--;
    }
    int main()
    {
        in(n);in(m);in(T);int s,t;
        for (int i=1;i<=n;i++)  tree[i].val=tree[i].minn=MAXINT,tree[i].st=i;
        for (int i=1;i<=m;i++)
        {
            in(e[i].u);in(e[i].v);in(s);in(t);e[i].w=t;
            insert1(s,i);insert2(t,i);
            tree[i+n].val=tree[i+n].minn=t;tree[i+n].st=i+n;tree[i+n].sum=1;
        }
        for (int x=0;x<T;x++)
        {
            for (Edge *i=prev1[x];i;i=i->next)  ins(i->to);
            for (Edge *i=prev2[x];i;i=i->next)  del(i->to);
            puts(cnt?"No":"Yes");
        }
    }
  • 相关阅读:
    dotnet run urls=http://*:8080
    内敛声明变量
    C#反射赋值(更新时用)
    mysql---auto_increment=10啥意思呢?
    vscode--代码折叠与展开
    联想启天M410台式机的清除BIOS密码
    AntD是什么?
    react-router-dom 中文文档
    Recoil是什么?
    sql server查看建表的创建代码?
  • 原文地址:https://www.cnblogs.com/wzzkaifa/p/7402618.html
Copyright © 2011-2022 走看看