Descriptionios
神犇有一個n個節點的圖。因爲神犇是神犇,因此在T時間內一些邊會出現後消失。神犇要求出每一時間段內這個圖是不是二分圖。這麼簡單的問題神犇固然會作了,因而他想考考你。數組
Inputmarkdown
輸入數據的第一行是三個整數n,m,T。
第2行到第m+1行。每行4個整數u,v,start,end。post
第i+1行的四個整數表示第i條邊鏈接u,v兩個點。這條邊在start時刻出現。在第end時刻消失。
Outputui
輸出包括T行。spa
在第i行中。假設第i時間段內這個圖是二分圖。那麼輸出「Yes」。不然輸出「No」,不含引號。
Sample Input.net
3 3 3code
1 2 0 2blog
2 3 0 3ip
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");
}
}