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

    [BZOJ4025]二分图

    试题描述

    神犇有一个n个节点的图。因为神犇是神犇,所以在T时间内一些边会出现后消失。神犇要求出每一时间段内这个图是否是二分图。这么简单的问题神犇当然会做了,于是他想考考你。

    输入

    输入数据的第一行是三个整数n,m,T。
    第2行到第m+1行,每行4个整数u,v,start,end。第i+1行的四个整数表示第i条边连接u,v两个点,这条边在start时刻出现,在第end时刻消失。

    输出

    输出包含T行。在第i行中,如果第i时间段内这个图是二分图,那么输出“Yes”,否则输出“No”,不含引号。

    输入示例

    3 3 3
    1 2 0 2
    2 3 0 3
    1 3 1 2

    输出示例

    Yes
    No
    Yes

    数据规模及约定

    n<=100000,m<=200000,T<=100000,1<=u,v<=n,0<=start<=end<=T。

    题解

    一个图是二分图的充要条件就是不存在奇环。

    那么我们动态树维护一下删除时间最大生成树。每次加入一条边,如果形成奇环,那么计数器 +1,然后再环中最小权值(权值即删除时间)的时刻计数器 -1;那么删除时如果是树边就在 LCT 上删去,否则跳过。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #include <vector>
    using namespace std;
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 100010
    #define maxm 200010
    #define maxnode 300010
    #define oo 2147483647
    
    struct Node {
    	int delt, mn, v, siz;
    	bool rev;
    	Node(): rev(0) {}
    	Node(int _, int __): delt(_), v(__) {}
    } ns[maxnode];
    int fa[maxnode], ch[maxnode][2], S[maxnode], top;
    bool isrt(int u) { return !fa[u] || (ch[fa[u]][0] != u && ch[fa[u]][1] != u); }
    void maintain(int o) {
    	ns[o].mn = o; ns[o].siz = ns[o].v;
    	for(int i = 0; i < 2; i++) if(ch[o][i]) {
    		int tmp = ns[ch[o][i]].mn, &me = ns[o].mn;
    		if(ns[tmp].delt < ns[me].delt) me = tmp;
    		ns[o].siz += ns[ch[o][i]].siz;
    	}
    	return ;
    }
    void pushdown(int o) {
    	if(!ns[o].rev) return ;
    	swap(ch[o][0], ch[o][1]);
    	for(int i = 0; i < 2; i++) if(ch[o][i])
    		ns[ch[o][i]].rev ^= 1;
    	ns[o].rev = 0;
    	return ;
    }
    void rotate(int u) {
    	int y = fa[u], z = fa[y], l = 0, r = 1;
    	if(!isrt(y)) ch[z][ch[z][1]==y] = u;
    	if(ch[y][1] == u) swap(l, r);
    	fa[u] = z; fa[y] = u; fa[ch[u][r]] = y;
    	ch[y][l] = ch[u][r]; ch[u][r] = y;
    	maintain(y); maintain(u);
    	return ;
    }
    void splay(int u) {
    	int t = u; S[top = 1] = t;
    	while(!isrt(t)) S[++top] = fa[t], t = fa[t];
    	while(top) pushdown(S[top--]);
    	while(!isrt(u)) {
    		int y = fa[u], z = fa[y];
    		if(!isrt(y)) {
    			if(ch[y][0] == u ^ ch[z][0] == y) rotate(u);
    			else rotate(y);
    		}
    		rotate(u);
    	}
    	return ;
    }
    void access(int u) {
    	splay(u); ch[u][1] = 0; maintain(u);
    	while(fa[u]) splay(fa[u]), ch[fa[u]][1] = u, maintain(fa[u]), splay(u);
    	return ;
    }
    void makeroot(int u) {
    	access(u); ns[u].rev ^= 1;
    	return ;
    }
    void link(int a, int b) {
    	makeroot(b); fa[b] = a;
    	return ;
    }
    void cut(int a, int b) {
    	makeroot(a); access(b);
    	if(fa[a] != b) return ;
    	ch[b][0] = fa[a] = 0; maintain(b);
    	return ;
    }
    int _mn, _siz;
    void query(int a, int b) {
    	makeroot(a); access(b);
    	_mn = ns[b].mn; _siz = ns[b].siz;
    	return ;
    }
    bool same(int a, int b) {
    	makeroot(a); access(b);
    	while(!isrt(a)) a = fa[a];
    	return a == b;
    }
    
    struct Edge {
    	int u, v, st, en;
    	Edge() {}
    	Edge(int _1, int _2, int _3, int _4): u(_1), v(_2), st(_3), en(_4) {}
    	bool operator < (const Edge& t) const { return st != t.st ? st < t.st : en < t.en; }
    } es[maxm];
    vector <int> dele[maxn];
    
    int del[maxn];
    
    int main() {
    	int n = read(), m = read(), T = read();
    	
    	for(int i = 1; i <= n; i++) ns[i] = Node(oo, 0), maintain(i);
    	for(int i = 1; i <= m; i++) {
    		int u = read(), v = read(), a = read(), b = read();
    		es[i] = Edge(u, v, a, b);
    	}
    	sort(es + 1, es + m + 1);
    	for(int i = 1; i <= m; i++)
    		if(es[i].st != es[i].en) dele[es[i].en].push_back(i);
    	int tot = 0;
    	for(int t = 0, i = 1; t < T; t++) {
    		tot -= del[t];
    		for(int j = 0; j < dele[t].size(); j++) {
    			int e = dele[t][j];
    			cut(es[e].u, e + n); cut(e + n, es[e].v);
    		}
    		for(; i <= m && t >= es[i].st; i++) {
    			if(es[i].st == es[i].en) continue;
    			int u = es[i].u, v = es[i].v;
    			ns[i+n] = Node(es[i].en, 1);
    			if(same(u, v)) {
    				query(u, v);
    				if(_siz & 1) ; else tot++, del[min(ns[_mn].delt,es[i].en)]++;
    				if(ns[_mn].delt < es[i].en) {
    					cut(es[_mn-n].u, _mn); cut(_mn, es[_mn-n].v);
    					link(u, i + n); link(i + n, v);
    				}
    			}
    			else {
    				link(u, i + n); link(i + n, v);
    			}
    		}
    		puts(tot ? "No" : "Yes");
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    精选30道Java笔试题解答
    ASM
    Java Decompiler Plugin For Eclipse IDE
    AMQ5540, AMQ5541 and AMQ5542, application did not supply a user ID and password, 2035 MQRC_NOT_AUTHORIZED
    Shell脚本中的export
    Linux set unset命令
    shell中${}的妙用
    ubuntu alsa2
    ubuntu alsa
    计算机启动boot
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6699488.html
Copyright © 2011-2022 走看看