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

  • 相关阅读:
    高级特性(4)- 数据库编程
    UVA Jin Ge Jin Qu hao 12563
    UVA 116 Unidirectional TSP
    HDU 2224 The shortest path
    poj 2677 Tour
    【算法学习】双调欧几里得旅行商问题(动态规划)
    南洋理工大学 ACM 在线评测系统 矩形嵌套
    UVA The Tower of Babylon
    uva A Spy in the Metro(洛谷 P2583 地铁间谍)
    洛谷 P1095 守望者的逃离
  • 原文地址:https://www.cnblogs.com/functionendless/p/9470217.html
Copyright © 2011-2022 走看看