比赛描述
给定一个无向图,一共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]); } }