南邮 OJ 1044 连通 OR 不连通

连通 OR 不连通

时间限制(普通/Java) :  1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 445            测试通过 : 89 

比赛描述

给定一个无向图,一共n个点,请编写一个程序实现两种操作:

D x y 从原图中删除连接x,y节点的边。

Q x y 询问x,y节点是否连通



输入

第一行两个数n,m(5<=n<=100000,1<=m<=100000)

接下来m行,每行一对整数 x y (x,y<=n),表示x,y之间有边相连。保证没有重复的边。

接下来一行一个整数 q(q<=100000)

以下q行每行一种操作,保证不会有非法删除。

输出

按询问次序输出所有Q操作的回答,连通的回答C,不连通的回答D

样例输入

3 3
1 2
1 3
2 3
5
Q 1 2
D 1 2
Q 1 2
D 3 2
Q 1 2

样例输出

C
C
D

题目来源

NUAA


/* 307MS
#include<iostream>
#include<map>
#define MAX_N 100001
using namespace std;

int root[MAX_N];
char result[MAX_N];

struct edge{
	int a,b;
	bool del;
}e[MAX_N],q[MAX_N];

void init(int n){
	for(int i=1;i<=n;i++){
		root[i] = i;
	}
}

int getRoot(int i){
	return root[i]==i ? i : root[i]=getRoot(root[i]);	//TL
}

void Union(int a, int b){
	int ra=getRoot(a),rb=getRoot(b);
	if(ra!=rb){
		root[ra] = root[rb];
	}
}

bool find(int a, int b){
	return getRoot(a)==getRoot(b);
}

int main(){
	int n,m,i,qNum,outNo;
	char cmd[2];
	map<int,bool> willDel;
	scanf("%d%d",&n,&m);
	init(n);
	for(i=0;i<m;i++){
		scanf("%d%d",&e[i].a,&e[i].b);
		if(e[i].a > e[i].b){
			e[i].a ^= e[i].b;
			e[i].b ^= e[i].a;
			e[i].a ^= e[i].b;
		}
	}
	scanf("%d",&qNum);
	for(i=0;i<qNum;i++){
		scanf("%s%d%d",cmd,&q[i].a,&q[i].b);
		if(q[i].a > q[i].b){
			q[i].a ^= q[i].b;
			q[i].b ^= q[i].a;
			q[i].a ^= q[i].b;
		}
		if('D'==*cmd){
			q[i].del = 1;
			willDel[ q[i].a*MAX_N+q[i].b ] = 1;
		}
	}
	for(i=0;i<m;i++){								//不需要删除的边先连上
		if(!willDel[ e[i].a*MAX_N+e[i].b ]){
			Union(e[i].a,e[i].b);
		}
	}
	outNo=0;
	for(i=qNum-1; i>=0; i--){						//反向操作,将删除的边一条条加上
		if(q[i].del){
			Union(q[i].a,q[i].b);
		}else{
			if( find(q[i].a,q[i].b) ){
				result[outNo++]='C';
			}else{
				result[outNo++]='D';
			}
		}
	}
	for(i=outNo-1;i>=0;i--){
		printf("%c\n",result[i]);
	}
}
*/


/*
// 237MS
#include<iostream>
#include<set>
#define MAX_N 100001
using namespace std;

int root[MAX_N];
char result[MAX_N];

struct edge{
	int a,b;
	bool del;
}e[MAX_N],q[MAX_N];

void init(int n){
	for(int i=1;i<=n;i++){
		root[i] = i;
	}
}

int getRoot(int i){
	return root[i]==i ? i : root[i]=getRoot(root[i]);
}

void Union(int a, int b){
	int ra=getRoot(a),rb=getRoot(b);
	if(ra!=rb){
		root[ra] = root[rb];
	}
}

bool find(int a, int b){
	return getRoot(a)==getRoot(b);
}

int main(){
	int n,m,i,qNum,outNo;
	char cmd[2];
	set<int> willDel;
	scanf("%d%d",&n,&m);
	init(n);
	for(i=0;i<m;i++){
		scanf("%d%d",&e[i].a,&e[i].b);
		if(e[i].a > e[i].b){
			e[i].a ^= e[i].b;
			e[i].b ^= e[i].a;
			e[i].a ^= e[i].b;
		}
	}
	scanf("%d",&qNum);
	for(i=0;i<qNum;i++){
		scanf("%s%d%d",cmd,&q[i].a,&q[i].b);
		if(q[i].a > q[i].b){
			q[i].a ^= q[i].b;
			q[i].b ^= q[i].a;
			q[i].a ^= q[i].b;
		}
		if('D'==*cmd){
			q[i].del = 1;
			willDel.insert(q[i].a*MAX_N+q[i].b);
		}
	}
	for(i=0;i<m;i++){								//不需要删除的边先连上
		if(!willDel.count(e[i].a*MAX_N+e[i].b)){
			Union(e[i].a,e[i].b);
		}
	}
	outNo=0;
	for(i=qNum-1; i>=0; i--){						//反向操作,将删除的边一条条加上
		if(q[i].del){
			Union(q[i].a,q[i].b);
		}else{
			if( find(q[i].a,q[i].b) ){
				result[outNo++]='C';
			}else{
				result[outNo++]='D';
			}
		}
	}
	for(i=outNo-1;i>=0;i--){
		printf("%c\n",result[i]);
	}
}
*/




// 229MS
#include<iostream>
#include<set>
#define MAX_N 100001
using namespace std;

int root[MAX_N];
char result[MAX_N];

struct edge{
	int a,b;
	bool del;
}e[MAX_N],q[MAX_N];

void init(int n){
	for(int i=1;i<=n;i++){
		root[i] = i;
	}
}

int getRoot(int i){
	return root[i]==i ? i : root[i]=getRoot(root[i]);
}

void Union(int a, int b){
	int ra=getRoot(a),rb=getRoot(b);
	if(ra!=rb){
		root[ra] = root[rb];
	}
}

bool find(int a, int b){
	return getRoot(a)==getRoot(b);
}

int main(){
	int n,m,i,qNum,outNo;
	char cmd;
	set<int> willDel;
	scanf("%d%d",&n,&m);
	init(n);
	for(i=0;i<m;i++){
		scanf("%d%d",&e[i].a,&e[i].b);
		if(e[i].a > e[i].b){
			e[i].a ^= e[i].b;
			e[i].b ^= e[i].a;
			e[i].a ^= e[i].b;
		}
	}
	scanf("%d",&qNum);
	for(i=0;i<qNum;i++){
		getchar();
		scanf("%c%d%d",&cmd,&q[i].a,&q[i].b);
		if(q[i].a > q[i].b){
			q[i].a ^= q[i].b;
			q[i].b ^= q[i].a;
			q[i].a ^= q[i].b;
		}
		if('D'==cmd){
			q[i].del = 1;
			willDel.insert(q[i].a*MAX_N+q[i].b);
		}
	}
	for(i=0;i<m;i++){								//不需要删除的边先连上
		if(!willDel.count(e[i].a*MAX_N+e[i].b)){
			Union(e[i].a,e[i].b);
		}
	}
	outNo=0;
	for(i=qNum-1; i>=0; i--){						//反向操作,将删除的边一条条加上
		if(q[i].del){
			Union(q[i].a,q[i].b);
		}else{
			if( find(q[i].a,q[i].b) ){
				result[outNo++]='C';
			}else{
				result[outNo++]='D';
			}
		}
	}
	for(i=outNo-1;i>=0;i--){
		printf("%c\n",result[i]);
	}
}







你可能感兴趣的:(ACM,or,连通,南邮OJ,不连通)