[Bzoj4025] FIG bipartite

Description

Ben has a god \ (n-\) FIG nodes. Ben Ben because God is God, so over time T after the disappearance of some of the side will appear. Ben God requires of each period whether this figure is a bipartite graph. Such a simple question of God, of course Ben would do, and he wanted to test you.

Input

The first line of input data is three integer \ (n-\) , \ (m \) , \ (T \) .
The second row through \ (m + 1 \) rows, each row four integer \ (U \) , \ (V \) , \ (Start \) , \ (End \) . The first \ (i + 1 \) four line represents the integer \ (I \) edges connected \ (U \) , \ (V \) two points, in this edge \ (Start \) appears in time, in the first \ (end \) disappear in time.

Output

Output comprising \ (T \) line. In the i-th row, if the first \ (i \) This is a bipartite graph in FIG period, the output " \ (Yes \) ", otherwise, outputs " \ (No \) ", without quotes.

Sample Input

3 3 3

1 2 0 2

2 3 0 3

1 3 1 2

Sample Output

Yes

No

Yes

HINT

Sample Description:
0, the two sides 1-2 and 2-3 appear.
The first period of time, this graph is a bipartite graph, output \ (Yes \) .
1 time, a 1-3 edge occurs.
The second period, this figure is not a bipartite graph, output \ (No \) .
2 time, the disappearance of the two edges 1-2 and 1-3.
The third period, only one edge 2-3, the graph is a bipartite graph, output \ (Yes \) .

数据范围:
\ (n \ leq 100000 \) , \ (m \ leq 200000 \) , \ (T \ leq 100000 \) , \ (1 \ leq u, v \ leq n \) , \ (0 \ leq start \ leq end \ leq T \) .


idea

First of all, how to determine the bipartite graph is a problem [thinking]
given conclusion - the number of points \ (\ geq 2 \) and no odd ring.
Think about feeling quite right, that is to say between any two points parity path length is the same, the even number is two points in the same "collection" is odd in a different "collections"

So we can maintain a tree, plus side if it had been connected to two points, determine what the distance between two points is currently not an odd, if not, then add the edge is not bipartite graph.

But this question is not only a plus side, there are border erase.
Then there are two approaches, \ (LCT \) or segment tree partition.

A practice: LCT

Dynamically maintains spanning tree slightly.
All the while adding chronological order.
If no-show ring is directly connected to the side
If there is a ring: if odd ring mark from the current time to ring the earliest time of deletion "is not a bipartite graph", even without ring mark. Delete to delete the minimum time on the ring side.
Border Erase operation, if the edge has been deleted regardless, it has not been deleted deleted.
(But I'm just mouth Hu, I did not write this practice ...)

Practice two: divide and conquer tree line

In time segment tree index construction, marking each edge in time of its existence.
Segment tree traversal of each node, with disjoint-set Maintenance "tree", just to maintain it at each point and check parity set root path on the line.
Note:
1. Online section of a tree node discovery "is not a bipartite graph" direct labeling at all time points it represents the number of "not bipartite graph", no longer down recursion.
2. Due to "back out", i.e., to delete the edge disjoint-set, so the path can not be compressed.

Without compression path of disjoint-set, each time looking \ (fa \) is \ (O (logn) \) , each point of looking for \ (O (logn) \) times, so the total complexity \ (O ( nlog ^ 2n) \)


Code

\ (WA \) for a long long long long time ......
I saw I \ (WA \) a cry out ooo, ooo ......

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
 
using namespace std;
 
int read(){
    int x=0;
    char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    return x;
}
 
const int N = 100005;
 
int n,m,T;
 
struct edge{ int u,v; }d[N*2];
int tot;
 
int root,cnt,ch[N*2][2];
vector<edge> seg[N*2];
void build(int x,int l,int r){
    if(l==r) return;
    int mid=(l+r)>>1;
    build(ch[x][0]=++cnt,l,mid);
    build(ch[x][1]=++cnt,mid+1,r);
}
void ins(int x,int l,int r,int L,int R,int c){
    if(l==L && r==R) { seg[x].push_back(d[c]); return; }
    int mid=(l+r)>>1;
    if(R<=mid) ins(ch[x][0],l,mid,L,R,c);
    else if(L>mid) ins(ch[x][1],mid+1,r,L,R,c);
    else{
        ins(ch[x][0],l,mid,L,mid,c);
        ins(ch[x][1],mid+1,r,mid+1,R,c);
    }
}
 
int ans[N],fa[N],val[N],pre[N],sz[N];
int getfa(int x) { 
    if(x==fa[x]) return x;
    int z=getfa(fa[x]);
    val[x]=val[fa[x]]^pre[x];
    return z;
}
void work(int x,int l,int r){
    int flag=1;
    vector<edge> opt;
    for(int i=0;i<seg[x].size();i++){
        int fu=getfa(seg[x][i].u),fv=getfa(seg[x][i].v);
        if(fu==fv){
            if(val[seg[x][i].u]==val[seg[x][i].v]) flag=0;
        }
        else{
            if(sz[fu]>sz[fv]) swap(fu,fv);
            fa[fu]=fv; sz[fv]+=sz[fu];
            pre[fu]=val[seg[x][i].u]^val[seg[x][i].v]^1;
            opt.push_back((edge){fu,fv});
        }
    }
     
    if(l<r && flag){
        int mid=(l+r)>>1;
        work(ch[x][0],l,mid); 
        work(ch[x][1],mid+1,r);
    }
    if(l==r) ans[l]=flag;
     
    for(int i=opt.size()-1;i>=0;i--){
        pre[opt[i].u]=val[opt[i].u]=0; //别忘了把 val 也清零!
        sz[opt[i].v]-=sz[opt[i].u];
        fa[opt[i].u]=opt[i].u;
    }
}
 
int main()
{
    int u,v,st,ed;
    n=read(); m=read(); T=read();
     
    build(root=++cnt,1,T);
    while(m--){
        u=read(); v=read(); st=read()+1; ed=read()+1;
        if(st==ed) continue;
        d[++tot]=(edge){u,v};
        ins(root,1,T,st,ed-1,tot);
    }
     
    for(int i=1;i<=n;i++) fa[i]=i,val[i]=pre[i]=0,sz[i]=1;
    work(root,1,T);
    for(int i=1;i<=T;i++)
        if(ans[i]) printf("Yes\n");
        else printf("No\n");
     
    return 0;
} 

Guess you like

Origin www.cnblogs.com/lindalee/p/11372033.html