EOJ:Quick Answer
Quick Answer
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submits: 86 | Accepted: 12 |
Description
Joe is fond of computer games. Now, he must solve a puzzling situation. In front of his eyes lies a huge map with fortified towns. His enemy is a very powerful and tricky character who can connect and disconnect the towns by giving some commands. Two towns are connected if they have been directly connected or interconnected through some other connected towns at some moment in time. When a town is disconnected it gets isolated and clears its own connection history, not the connection history of the other towns. Each connection is bi-directional. Initially the towns are isolated. Joe is asked to answer quickly if two towns are connected, according to the history of the character' commands.
Input
Each data set in the input stands for a particular map and the associated character's commands, as follows:
1) The number of towns on the map N (N ≤ 10000);
2) A list of commands of the form:
a) c towni townj, where towni and townj are integers from 1 to no_of_towns. The command means that towni and townj get connected.
b) d towni, where towni is an integer from 1 to no_of_towns. The command means that towni gets disconnected.
c) q towni townj, where towni and townj are integers from 1 to no_of_towns. The command stands for the question: is towni connected with townj?
d) e, that ends the list of commands
Each command is on a separate line. Commands (a), (b), (c) can appear in any order. The towns' connectivity is updated after each command of type (a) or (b). Each command of type (c) is processed according to the current configuration.
Output
Write a program counts the number of yes answers an the number of no answers to questions of the kind: is towni connected with townj?
There are N1 yes answered questions and N2 no answered questions.
The program prints these two numbers to the standard output on the same line, in the order: N1, N2 as shown in the following:
Sample Input
4 c 1 2 c 3 4 q 1 3 c 2 3 q 1 4 d 2 q 4 1 q 2 4 e
Sample Output
2 , 2
http://202.120.106.94/onlinejudge/problemshow.php?pro_id=96
_________________________________________________________________________________________________
并查集问题。
本题主要的问题在于会删点,但是这个删点与一般的删点不同,删点一个点之后,通过这个点作为中转的其他相连的点不变。
例如A-B,B-C那么A通过B和C相连,如果这时删掉B,那么A和C还是相连的。
基于这个特殊的“删点”就有以下的算法
给每个点一个ID,如果删点该点,那么就把这个点的ID变成最大的ID号+1。
例如:A的ID是1,B的ID是2,C的ID是3 。这时删掉B,那么B的ID变成4,而A和C还是通过2这个点相连,但实际上2这个ID表示的点已经不存在了,只是个虚拟的点。
1 #include<stdio.h>
2 int parent[50005],id[10005];
3 int ans1,ans2,a,b,i,n;
4 char c;
5 int find_parent(int a)
6 {
7 int temp;
8 temp=a;
9 if (temp!=parent[temp])
10 temp=find_parent(parent[temp]);
11 parent[a]=temp;
12 return temp;
13 }
14 void merge(int a,int b)
15 {
16 int x,y;
17 x=find_parent(id[a]);
18 y=find_parent(id[b]);
19 parent[x]=y;
20 }
21 void ques(int a,int b)
22 {
23 int x,y;
24 x=find_parent(id[a]);
25 y=find_parent(id[b]);
26 if (x==y)
27 ans1++;
28 else ans2++;
29 }
30 void discon(int a)
31 {
32 id[a]=++n;
33 parent[n]=n;
34 }
35 void work()
36 {
37 for (i=1;i<=n;i++)
38 {
39 id[i]=i;
40 parent[i]=i;
41 }
42 ans1=0;
43 ans2=0;
44 while (1)
45 {
46 scanf("%c",&c);
47 while (c!='e'&&c!='d'&&c!='c'&&c!='q')
48 scanf("%c",&c);
49 switch (c)
50 {
51 case 'e':printf("%d , %d\n",ans1,ans2);return;
52 case 'c':scanf("%d%d",&a,&b);merge(a,b);break;
53 case 'q':scanf("%d%d",&a,&b);ques(a,b);break;
54 case 'd':scanf("%d",&a);discon(a);break;
55 }
56 }
57 }
58 int main()
59 {
60 while (scanf("%d",&n)!=EOF)
61 work();
62 return 0;
63 }