[bzoj4025]二分图
LCT一和别的东西扯上关系怎么就这么sxbk。。
如果是问这个图是否是树的话就是常见姿势了:把边也当成点,然后用lct维护 以边的删除时间为权值 的最大生成树。
但现在要求问是否是二分图。。。二分图就是说图中没有节点数为奇数的环。
还是维护最大生成树,但是加边、形成环的时候的判断不一样了:
会形成偶环的话就不连;(一条边如果可以和已有链形成偶环,并且这条边在之后和某些边构成一个奇环,那么已有链也可以和那些边构成奇环)
会形成奇环的话就维护最大生成树,记录并在树中删除环上权值最小的边。
记录一条边就是说,有这条边在的时候这个图里有奇环。所以如果图中被记录的边都过了删除时间的话,这个图就是二分图。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int maxn=300023; 6 const int inf=1000233333; 7 struct zs{ 8 int u,v,del,pre; 9 }e[maxn];int tot,last[maxn]; 10 struct zs1{int pre;}e1[maxn];int last1[maxn]; 11 bool intree[maxn],sur[maxn]; 12 int sum[maxn],cnt; 13 14 int fa[maxn],ch[maxn][2],mnpos[maxn],sz[maxn],st[maxn],top; 15 bool rev[maxn]; 16 17 int i,j,k,n,m,T,x,y,l,r; 18 19 int ra;char rx; 20 inline int read(){ 21 rx=getchar(),ra=0; 22 while(rx<'0'||rx>'9')rx=getchar(); 23 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 24 } 25 26 inline bool isrt(int x){ 27 return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x; 28 } 29 inline void pushdown(int x){ 30 if(!rev[x])return; 31 swap(ch[x][0],ch[x][1]),rev[ch[x][0]]^=1,rev[ch[x][1]]^=1, 32 rev[x]=0; 33 } 34 inline void upd(int x){ 35 mnpos[x]= mnpos[ ch[x][ e[mnpos[ch[x][0]]].del>e[mnpos[ch[x][1]]].del ] ]; 36 if(x<=tot&&e[x].del<e[mnpos[x]].del)mnpos[x]=x; 37 sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+(x>tot); 38 } 39 inline void rotate(int x){ 40 int f=fa[x],gfa=fa[f],l=ch[f][1]==x,r=l^1; 41 if(!isrt(f))ch[gfa][ ch[gfa][1]==f ]=x; 42 fa[ ch[f][l]=ch[x][r] ]=f,fa[ fa[ ch[x][r]=f ]=x ]=gfa, 43 upd(f); 44 } 45 inline void splay(int x){ 46 int f=x,gfa; 47 for(st[top=1]=f;!isrt(f);st[++top]=(f=fa[f])); 48 while(top)pushdown(st[top--]); 49 while(!isrt(x)){ 50 f=fa[x],gfa=fa[f]; 51 if(!isrt(f)) 52 rotate(((ch[f][1]==x)^(ch[gfa][1]==f))?x:f); 53 rotate(x); 54 } 55 upd(x); 56 } 57 inline void access(int x){ 58 for(int rc=0;x;rc=x,x=fa[x]) 59 splay(x),ch[x][1]=rc,upd(x); 60 } 61 inline void makert(int x){ 62 access(x),splay(x),rev[x]^=1; 63 } 64 inline void link(int x,int y){ 65 makert(x),fa[x]=y; 66 } 67 inline void cut(int x,int y){ 68 makert(x),access(y),splay(y),fa[x]=ch[y][0]=0,upd(y); 69 } 70 inline int getfa(int x){ 71 for(access(x),splay(x);ch[x][0];x=ch[x][0]); 72 return x; 73 } 74 75 76 int main(){ 77 n=read(),m=read(),T=read(); 78 for(i=1;i<=m;i++){ 79 x=read()+m,y=read()+m,l=read()+1,r=read(); 80 if(l>r)continue; 81 e[++tot]=(zs){x,y,r,last[l]};last[l]=tot; 82 e1[tot].pre=last1[r],last1[r]=tot; 83 } 84 e[0].del=inf; 85 for(i=1;i<=tot;i++)mnpos[i]=i; 86 for(i=1;i<=T;i++){ 87 for(j=last[i];j;j=e[j].pre){ 88 x=e[j].u,y=e[j].v;//printf("x,y: %d %d\n",x,y); 89 if(getfa(x)==getfa(y)){ 90 makert(x),access(y),splay(y);int pos=mnpos[y]; 91 if(sz[y]&1){ 92 if(e[j].del>e[pos].del) 93 cut(e[pos].u,pos),cut(pos,e[pos].v), 94 sum[e[pos].del]++,cnt++,intree[pos]=0,sur[pos]=1, 95 link(x,j),link(j,y),intree[j]=1 96 ;//,printf("cut:(%d) %d %d\nlink: %d %d\n",pos,e[pos].u-m,e[pos].v-m,x,y); 97 else sum[e[j].del]++,cnt++,sur[j]=1;//,printf("!! %d\n",e[pos].del); 98 } 99 }else link(x,j),link(j,y),intree[j]=1;//,printf("link: %d %d\n",x-m,y-m); 100 } 101 puts(cnt?"No":"Yes"); 102 for(j=last1[i];j;j=e1[j].pre) 103 if(intree[j])/*printf("cut:(%d) ",j),*/cut(e[j].u,j),cut(j,e[j].v);//,printf("%d %d\n",e[j].u-m,e[j].v-m); 104 else if(sur[j])cnt--,sum[e[j].del]--; 105 cnt-=sum[i]; 106 // printf(" %d\n",cnt); 107 } 108 109 return 0; 110 }
因为update写炸调了半天。。。