神犇有一个n个节点的图。因为神犇是神犇,所以在T时间内一些边会出现后消失。神犇要求出每一时间段内这个图是否是二分图。这么简单的问题神犇当然会做了,于是他想考考你。
标签:names 递归 代码 表示 desc 证明 -- 自己 return
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <iostream> #include <vector> #define MAXN 201000 using namespace std; int fa[MAXN],rak[MAXN],d[MAXN]; int s1[MAXN*2],s2[MAXN],ans[MAXN],top=0; struct edge{ int x,y,s,e; }; vector<edge> S; int n,m,t; int find(int x){ while(x!=fa[x]) x=fa[x]; return x; } int getdis(int x){ int ans=0; while(x!=fa[x]) ans^=d[x],x=fa[x]; return ans; } void mearge(int x,int y,int c){ if(rak[x]>rak[y]){ s1[++top]=y;s2[top]=1; fa[y]=x,d[y]=c; } else if(rak[y]>rak[x]){ s1[++top]=x;s2[top]=1; fa[x]=y;d[x]=c; } else{ rak[x]++;fa[y]=x; s1[++top]=y;s2[++top]=0; fa[y]=x,d[y]=c; } } void fenzhi(int l,int r,vector<edge> hh){ int now=top,mid=(l+r)/2; vector<edge> ll,rr; for(int i=0,len=hh.size();i<len;i++){ edge a=hh[i]; int x=a.x,y=a.y; if(a.s==l&&a.e==r){ int fx=find(x),fy=find(y),c=getdis(x)^getdis(y)^1; if(fx!=fy) mearge(fx,fy,c); else if(c&1){ for(int i=l;i<=r;i++) ans[i]=0; while(now!=top){ if(s2[top]==0) rak[fa[s1[top]]]--;// fa[s1[top]]=s1[top];d[s1[top]]=0;top--; } return; } } else if(a.e<=mid) ll.push_back(a); else if(a.s>mid) rr.push_back(a); else{ edge b=a; b.e=mid;ll.push_back(b); b=a;b.s=mid+1; rr.push_back(b); } } if(l==r) ans[l]=1; else fenzhi(l,mid,ll),fenzhi(mid+1,r,rr); while(now!=top){ if(s2[top]==0) rak[fa[s1[top]]]--;// fa[s1[top]]=s1[top];d[s1[top]]=0;top--; } } int main() { scanf("%d%d%d",&n,&m,&t); for(int i=1;i<=m;i++){ int x,y,s,t;scanf("%d%d%d%d",&x,&y,&s,&t);s++; if(s<=t) S.push_back((edge){x,y,s,t}); } for(int i=1;i<=n;i++) fa[i]=i,rak[i]=0,d[i]=0; for(int i=1;i<=n;i++) ans[i]=1; fenzhi(1,t,S); for(int i=1;i<=t;i++){ if(ans[i]) printf("Yes\n"); else printf("No\n"); } return 0; }
标签:names 递归 代码 表示 desc 证明 -- 自己 return
原文地址:http://www.cnblogs.com/renjianshige/p/7618107.html