[BZOJ4025] 二分图 LCT/(线段树分治+并查集)

4025: 二分图

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 2667  Solved: 989
[Submit][Status][Discuss]

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做法

 其实就是求是否有奇环。先求出最小生成树,随后根据非树边两点间的距离得出是否有奇环。

lct维护以边消失时间为权值的最大生成树。这样可以保证所有已经进入集合的非树边都不会从集合中出来再次成为树边。
从小到达枚举时间进行加边和删边。
加边判奇环,更新最大生成树和集合.
删边如果是最大生成树里的边就在lct中删掉。否则仅在集合中删掉即可。

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cmath>
  4 #include<cstdio>
  5 #include<algorithm>
  6 #include<cstring>
  7 #define maxn 400001
  8 using namespace std;
  9 inline int read() {
 10     char ch=getchar();int x=0,f=1;
 11     for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
 12     for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
 13     return x*f;
 14 }
 15 int n,m,T,ont[maxn*2],jh[maxn*2],tot,val[maxn*2];
 16 struct Edge {
 17     int to[maxn*4],nxt[maxn*4],head[maxn*2],cnt;
 18     Edge(){memset(head,-1,sizeof(head));cnt=0;}
 19     void add(int u,int v) {to[cnt]=v;nxt[cnt]=head[u];head[u]=cnt++;}
 20 }e1,e2;
 21 struct ASK {int u,v,w;}a[maxn*2];
 22 struct LCT {
 23     struct Data {
 24         int son[2],sz,fa,rev,mn;
 25     }t[maxn*2];
 26     bool isrt(int x) {return t[t[x].fa].son[0]!=x&&t[t[x].fa].son[1]!=x;}
 27     void pushdown(int x) {
 28         if(t[x].rev) {
 29             swap(t[x].son[0],t[x].son[1]);
 30             t[t[x].son[0]].rev^=1;t[t[x].son[1]].rev^=1;
 31             t[x].rev=0;
 32         }
 33     }
 34     void pushup(int x) {
 35         t[x].sz=t[t[x].son[0]].sz+t[t[x].son[1]].sz+(x>n);
 36         t[x].mn=x;
 37         if(val[t[t[x].son[0]].mn]<val[t[x].mn]) t[x].mn=t[t[x].son[0]].mn;
 38         if(val[t[t[x].son[1]].mn]<val[t[x].mn]) t[x].mn=t[t[x].son[1]].mn;
 39     }
 40     void rotate(int x) {
 41         int y=t[x].fa,z=t[y].fa;
 42         bool l=(t[y].son[1]==x),r=l^1;
 43         if(!isrt(y)) t[z].son[t[z].son[1]==y]=x;
 44         t[x].fa=z;t[y].fa=x;t[t[x].son[r]].fa=y;
 45         t[y].son[l]=t[x].son[r];t[x].son[r]=y;
 46         pushup(y);pushup(x);
 47     }
 48     void push(int x) {
 49         if(!isrt(x)) push(t[x].fa);
 50         pushdown(x);
 51     }
 52     void splay(int x) {
 53         push(x);
 54         while(!isrt(x)) {
 55             int y=t[x].fa,z=t[y].fa;
 56             if(!isrt(y)) {
 57                 if(t[y].son[0]==x^t[z].son[0]==y) rotate(x);
 58                 else rotate(y);
 59             }
 60             rotate(x);
 61         }
 62     }
 63     void access(int x) {for(int pre=0;x;pre=x,x=t[x].fa) {splay(x),t[x].son[1]=pre;pushup(x);}}
 64     void makert(int x) {access(x);splay(x);t[x].rev^=1;}
 65     void link(int x,int y) {makert(x);t[x].fa=y;}
 66     void cut(int x,int y) {makert(x);access(y);splay(y);t[y].son[0]=t[x].fa=0;}
 67     int find(int x) {access(x);splay(x);while(t[x].son[0]) x=t[x].son[0];return x;}
 68 }lct;
 69 void insert(int x,int u,int v,int w) {
 70     if(u==v) {jh[x]=1;tot++;return;}
 71     if(lct.find(u)!=lct.find(v)) {
 72         
 73         ont[x]=1;lct.link(u,n+x);lct.link(v,n+x);
 74     }
 75     else {
 76         lct.makert(v);lct.access(u);lct.splay(u);int tmp=lct.t[u].mn-n;
 77         if(a[tmp].w<a[x].w) {
 78             if(!(lct.t[u].sz&1)) {jh[tmp]=1;tot++;}
 79             lct.cut(a[tmp].u,tmp+n);lct.cut(a[tmp].v,tmp+n);
 80             lct.link(u,n+x);lct.link(v,n+x);
 81             ont[tmp]=0;ont[x]=1;
 82         }
 83         else {
 84             if(!(lct.t[u].sz&1)) {jh[x]=1;tot++;}
 85         }
 86     }
 87 }
 88 void del(int x,int u,int v,int w) {
 89     if(ont[x]) {lct.cut(u,x+n);lct.cut(v,x+n);}
 90     else if(jh[x]) tot--;
 91 }
 92 int main() {
 93     n=read(),m=read(),T=read();
 94     memset(val,27,sizeof(val));
 95     for(int i=1;i<=n;i++) lct.t[i].mn=i;
 96     for(int i=1;i<=m;i++) {
 97         a[i].u=read(),a[i].v=read();int s=read(),t=read();
 98         e1.add(s,i);e2.add(t,i);a[i].w=t;lct.t[n+i].sz=1;lct.t[n+i].mn=n+i;val[n+i]=t;
 99     }
100     for(int i=0;i<T;i++) {
101         for(int j=e1.head[i];j>=0;j=e1.nxt[j]) {
102             int to=e1.to[j];
103             insert(to,a[to].u,a[to].v,a[to].w);
104         }
105         for(int j=e2.head[i];j>=0;j=e2.nxt[j]) {
106             int to=e2.to[j];
107             del(to,a[to].u,a[to].v,a[to].w);
108         }
109         if(!tot) printf("Yes\n");
110         else printf("No\n");
111     }
112     return 0;
113 }
114 /*
115 45365
116 57727
117 */
View Code

 

posted @ 2018-11-29 13:19  wls001  阅读(216)  评论(0编辑  收藏  举报