zoukankan      html  css  js  c++  java
  • [BZOJ 4025] 二分图

    题目传送-BZOJ4025

    题意:

    有一张(n)个节点的无向图,其中边(i)(s_i)出现,(e_i)结束,并连接着节点(x,y).
    并保证(s_i < e_i le T),要求对于每个时间(tle T)输出此时的图是否是二分图。
    (nle100000,mle200000,Tle100000)

    题解:

    这是道好题,考到了线段树(分治)的思想,听说也叫整体二分?
    考虑如何做一个区间(时间)[L,R]中的所有答案:
    显然我们只考虑与这个区间有交集的边
    分两种:完全覆盖这个区间,部分覆盖这个区间。
    显然我们可以毫无顾虑的把第一类的边都加上
    此时如果已经不是二分图了,那显然直接GG了
    然后对于其它边我们只要递归下去处理就行了
    如何判断二分图并支持对图的修改:
    考虑按秩合并的带权并查集,这就不多说了
    复杂度的证明:
    空间:
    观察发现每个区间的处理需要有一个边集
    而每条边最多能在log个区间中出现(线段树的思想)
    那么总共的空间需求就是(m*log_2T)
    时间:
    同样一条边只能与log个区间相关,也就是说它只能被删加log次
    所以复杂度也是(m*log_2T)的?
    不知道我这样分析对不对,貌似@zhouzhendong大佬说这是(log^2)

    过程:

    已更新至我都错题集-updating
    并查集相关错误

    代码:

    const int N=100010,M=200010;
    int n,m,T;
    struct EDGE {
    	int x,y,s,t;
    	inline void in() {
    		read(x); read(y); read(s); read(t); ++s;
    	}
    };
    int ans[N];
    int cnt=0;
    namespace DSU {
    	int val[N],dep[N],fat[N];
    	struct TMP {
    		int fx,fy,dx,dy;
    	};//x merge to y -> dep[fx]<dep[fy]
    	stack<TMP> sta;
    	inline void Init() {
    		for(int i=1;i<=n;i++) 
    			fat[i]=i,dep[i]=1,val[i]=0;
    	}
    	inline pii father(int x) {
    		int ret=0;
    		while(x!=fat[x]) ret^=val[x],x=fat[x];
    		return mp(x,ret);
    	}
    	inline bool Merge(int x,int y) {
    		pii tx=father(x),ty=father(y);
    		int fx=tx.F,fy=ty.F,vx=tx.S,vy=ty.S;
    		if(dep[fx]>dep[fy]) swap(fx,fy);
    		int v=1^vx^vy;
    		if(fx==fy) return v==0;
    		sta.push((TMP) {fx,fy,dep[fx],dep[fy]});
    		fat[fx]=fy; val[fx]=v;
    		dep[fy]=max(dep[fy],dep[fx]+1);
    		return true;
    	}
    	inline void Split(int to) {
    		--cnt; assert(cnt>=0);
    		while((int)sta.size()!=to) {
    			// puts("?");
    			assert(!sta.empty());
    			TMP tmp=sta.top(); sta.pop();
    			int fx=tmp.fx,fy=tmp.fy,dx=tmp.dx,dy=tmp.dy;
    			dep[fx]=dx; dep[fy]=dy; fat[fx]=fx; val[fx]=0;
    		}
    	}
    }
    vector<EDGE> E;
    void Solve(int S,int T,vector<EDGE> &E) {
    	assert(S<=T);
    	if((int)E.size()==0) {
    		for(int i=S;i<=T;i++)
    			ans[i]=1;
    		return;
    	}
    	++cnt;
    	vector<EDGE> EL,ER; EL.clear(); ER.clear();
    	int top=DSU::sta.size(),mid=(S+T)>>1;
    	for(int i=0;i<(int)E.size();i++) {
    		EDGE e=E[i];
    		if(e.s<=S && T<=e.t) {
    			if(!DSU::Merge(e.x,e.y)) {
    				// puts("???");
    				for(int j=S;j<=T;j++)
    					ans[j]=0;
    				DSU::Split(top); return;
    			} 
    		} else {
    			if(e.s<=mid) EL.push_back(e);
    			if(e.t> mid) ER.push_back(e);
    		}
    	}
    	if(S==T) {ans[S]=1; DSU::Split(top); return;}
    	Solve(S,mid,EL); Solve(mid+1,T,ER);
    	DSU::Split(top); return;
    }
    signed main() {
    	// freopen("10.in","r",stdin);
    	// freopen("my.out","w",stdout);
    	mem(ans,-1);
    	read(n); read(m); read(T);
    	DSU::Init();
    	for(int i=1;i<=m;i++) {
    		EDGE e; e.in(); E.push_back(e);
    	}
    	Solve(1,T,E);
    	// for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    	for(int i=1;i<=n;i++) puts(ans[i] ? "Yes" : "No");
    	return 0;
    }
    /*
    3 3 3
    1 2 0 2
    2 3 0 3
    1 3 1 2
    */
    

    用时:1h

  • 相关阅读:
    mybatis 批量插入时候的一个注意点
    centos7 kubernetes单机安装
    debug 模式缓慢
    那些年,我们误解的 JavaScript 闭包
    maven仓库的配置
    闭包
    docker 搭建自己的github
    docker 搭建小型的node开发环境。
    jquery validate
    使用ueditor中的setContent() 时经常报innerHtml错误(笔记)
  • 原文地址:https://www.cnblogs.com/functionendless/p/9470217.html
Copyright © 2011-2022 走看看