• [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;
    }
    
  • 相关阅读:
    什么是 bean 的自动装配?
    什么是 Spring 的内部 bean?
    什么是 Spring 的 MVC 框架?
    Spring AOP and AspectJ AOP 有什么区别?
    解释 JDBC 抽象和 DAO 模块?
    volatile 类型变量提供什么保证?
    一个 Spring Bean 定义 包含什么?
    什么是 Spring MVC 框架的控制器?
    使用 Spring 访问 Hibernate 的方法有哪些?
    什么是 Callable 和 Future?
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6699488.html
Copyright © 2020-2023  润新知