程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> HDU 5333 Undirected Graph LCT+BIT

HDU 5333 Undirected Graph LCT+BIT

編輯:關於C++

 

Undirected Graph

Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 184 Accepted Submission(s): 38



Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

There is an undirected graph with n vertices and m edges. Then Yuta does q operations on this graph. Each operation is described by two integers L,R (1≤L≤R≤n) and can be split into three steps:

1. Delete all the edges which have at least one vertice outside the range [L,R].

2. Yuta wants you to tell him the number of connected component of the graph.

3. Restore the graph.

This task is too hard for Rikka to solve. Can you help her?
Input There are at most 100 testcases and there are at least 97 testcases with n,m,q≤1000.

For each testcase, the first line contains three numbers n,m,q (n,q≤105,m≤2×105).

Then m lines follow. Each line contains two numbers ui,vi (1≤ui,vi≤105) which describe an edge of the graph.

Then q lines follows. Each line contains two numbers Li,Ri (1≤L≤R≤n) which describe an operation.
Output For each operation you need print a single line with a single number - the answer of this operation.
Sample Input
3 3 2
1 2
1 3
2 3
1 2
1 3

Sample Output
2
1

Author XJZX
Source 2015 Multi-University Training Contest 4 題意:

 

給定n個點m條邊的無向圖(有自環有重邊) q個詢問

對於某個詢問 query : [l,r]

把所有的邊 形如 {u,v} u,v其中一個或者兩個都不在區間[l,r]上的 都刪除,求此時殘余圖的連通分量數。

每個詢問都是互相獨立的,也就是每個詢問都是從原圖刪除而來。

思路:\

感覺很有道理的樣子,寫了一發,卡常數卡死人了。。

 

#pragma comment(linker, /STACK:1024000000)
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
template 
inline bool rd(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
template 
inline void pt(T x) {
	if (x < 0) {
		putchar('-');
		x = -x;
	}
	if (x > 9) pt(x / 10);
	putchar(x % 10 + '0');
}
typedef long long ll;
typedef pair pii;
const int N = 1e5 + 100;
const int inf = 10000000;
struct BIT {
	int c[N], maxn;
	void init(int n) {
		maxn = n;
		memset(c, 0, (10 + n) *sizeof(int));
	}
	int lowbit(int x) { return x&-x; }
	int sum(int x) {
		int ans = 0;
		while (x)ans += c[x], x -= lowbit(x);
		return ans;
	}
	int query(int l, int r) {
		return sum(r) - sum(l - 1);
	}
	void change(int x, int val) {
		while (x<=maxn)c[x] += val, x += lowbit(x);
	}
}bit;
struct Node *null;
struct Node {
	Node *fa, *ch[2];
	int val;
	int mi, min_id, id;
	bool rev;
	inline void put() {
		printf(%d: fa:%d [%d,%d] val:%d ma:%d,%d rev:%d
, id, fa->id, ch[0]->id, ch[1]->id, val, mi, min_id, rev);
	}
	inline void clear(int _id) {
		fa = ch[0] = ch[1] = null;
		rev = 0;
		id = _id;
		mi = inf;
		min_id = 0;
		val = 0;
	}
	inline void push_up() {
		if (this == null)return;
		if (val) {
			mi = min(id, min(ch[0]->mi, ch[1]->mi));
			if (id <= min(ch[0]->mi, ch[1]->mi)) min_id = id;
			else if (ch[0]->mi < min(ch[1]->mi, id	))min_id = ch[0]->min_id;
			else min_id = ch[1]->min_id;			
		}
		else
		{
			mi = min(ch[0]->mi, ch[1]->mi);
			if (ch[0]->mi < ch[1]->mi)min_id = ch[0]->min_id;
			else min_id = ch[1]->min_id;
		}
	}
	inline void push_down() {
		if (this == null)return;
		if (rev) {
			ch[0]->flip();
			ch[1]->flip();
			rev = 0;
		}
	}
	inline void setc(Node *p, int d) {
		ch[d] = p;
		p->fa = this;
	}
	inline bool d() {
		return fa->ch[1] == this;
	}
	inline bool isroot() {
		return fa == null || fa->ch[0] != this && fa->ch[1] != this;
	}
	inline void flip() {
		if (this == null)return;
		swap(ch[0], ch[1]);
		rev ^= 1;
	}
	inline void go() {//從鏈頭開始更新到this  
		if (!isroot())fa->go();
		push_down();
	}
	inline void rot() {
		Node *f = fa, *ff = fa->fa;
		int c = d(), cc = fa->d();
		f->setc(ch[!c], c);
		this->setc(f, !c);
		if (ff->ch[cc] == f)ff->setc(this, cc);
		else this->fa = ff;
		f->push_up();
	}
	inline Node*splay() {
		go();
		while (!isroot()) {
			if (!fa->isroot())
				d() == fa->d() ? fa->rot() : rot();
			rot();
		}
		push_up();
		return this;
	}
	inline Node* access() {//access後this就是到根的一條splay,並且this已經是這個splay的根了  
		for (Node *p = this, *q = null; p != null; q = p, p = p->fa) {
			p->splay()->setc(q, 1);
			p->push_up();
		}
		return splay();
	}
	inline Node* find_root() {
		Node *x;
		for (x = access(); x->push_down(), x->ch[0] != null; x = x->ch[0]);
		return x;
	}
	void make_root() {
		access()->flip();
	}
	void cut() {//把這個點的子樹脫離出去  
		access();
		ch[0]->fa = null;
		ch[0] = null;
		push_up();
	}
	void cut(Node *x) {
		if (this == x || find_root() != x->find_root())return;
		else {
			x->make_root();
			cut();
		}
	}
	void link(Node *x) {
		if (find_root() == x->find_root())return;
		else {
			make_root(); fa = x;
		}
	}
};
Node pool[N], *tail;
Node *node[N];
void init(int n) {
	tail = pool;
	null = tail++;
	null->clear(0);
	for (int i = 1; i <= n; i++) {
		node[i] = tail++;
		node[i]->clear(i);
	}
}
void debug(Node *x) {
	if (x == null)return;
	x->put();
	debug(x->ch[0]);
	debug(x->ch[1]);
}
int n, m, q;
struct BST {
	int f[N];
	void init(int n) { for (int i = 1; i <= n; i++)f[i] = i; }
	int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }
	void Union(int u, int v) {
		u = find(u); v = find(v);
		if (u == v)return;
		if (u > v)swap(u, v);
		f[u] = v;
	}
}cha;
void insert(int x, int y) {
//	puts(**===);	for (int i = 1; i <= max(x, y); i++)debug(node[i]), puts();puts();
	if (cha.find(x) == cha.find(y)) {
		node[y]->access();
//		puts(**);	for (int i = 1; i <= max(x, y); i++)debug(node[i]), puts();puts();
		int id = node[y]->min_id;
		if (y <= id)return;
//		printf(change id:%d
, id);
		bit.change(id, -1);
		node[id]->val--;
		node[id]->cut(node[x]);
	}
	else cha.Union(x, y);
//	puts(---------);for (int i = 1; i <= x; i++)debug(node[i]), puts();puts();
	bit.change(y, 1);
	node[y]->make_root();
	node[y]->val++;
	node[y]->push_up();
	node[y]->fa = node[x];

//	puts(@@@@@@);for (int i = 1; i <= x; i++)debug(node[i]), puts();puts();
}
int ans[N];
struct {
	struct Edge {
		int to, nex, id;
	}edge[N << 1];
	int head[N], edgenum;
	void init(int n) {
		memset(head, -1, (10 + n) *sizeof(int));
		edgenum = 0;
	}
	void add(int u, int v, int id = 0) {
		Edge E = { v, head[u], id};
		edge[edgenum] = E;
		head[u] = edgenum++;
	}
}E, Q;
int main() {
	while (~scanf(%d%d%d, &n,&m,&q)) {
		E.init(n); Q.init(n); cha.init(n);
		for (int i = 0, u, v;i < m; i++) 
		{
			rd(u), rd(v);
			if (u == v) {i--, m--;continue;}
			if (u < v)E.add(v, u);else E.add(u, v);
		}
		for (int i = 0, u, v;i < q; i++) {
			rd(u); rd(v);
			Q.add(v, u, i);
		}
		bit.init(n);
		init(n);
		for (int i = 1; i <= n; i++)
		{
			for (int j = E.head[i]; ~j; j = E.edge[j].nex) 
				insert(i, E.edge[j].to);
			for (int j = Q.head[i]; ~j; j = Q.edge[j].nex)
				ans[Q.edge[j].id] = n - bit.query(Q.edge[j].to, i);
		}
		for (int i = 0; i < q; i++)	pt(ans[i]), puts();
	}
	return 0;
}
/*
7 9 1
1 2
1 3
1 5
1 6
4 7
4 6
2 7
6 2
4 3
2 7

ans:3
*/


 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved