[JSOI-2008] [Luo Gu P1197] - Star Wars

Star Wars

A long time ago, in a galaxy far far away, a dark empire against its super weapon ruler of the galaxy. One day, with a fortuitous
opportunity, a rebel destroyed the Imperial weapon, and the capture of nearly all galaxies planet. These planets straight tunnel through a special Ethernet each other
or indirectly connected. But it did not last long, and soon the Empire again create his super weapon. With the power of this super weapon, the empire began to plan
to destroy the planet Rebel occupation. As the planet continues to be destroyed, the communication channel between the two planets began unreliable up. Now, the rebels first
brought you a mission: to give Ethernet connectivity tunnel and the planet against the order of the empire between the original two planets to try to quickly find each
communication once occupied by the rebels after the strike planet fast number. (If two planets may communicate directly or indirectly through the existing Ethernet channels,
two planets in the same communication block).

[Input]
The first line of the input file contains two integers, N (1 <= N <= 2M) and M (1 <= M <= 200,000), respectively planet
The number and the number of Ethernet tunnel. Planet integer number of 0 ~ N-1. The next M rows, each row comprising two integers X, Y, where (0 <= X <> 
Y represents the "ether" x tunnel between planets and stars y, can communicate directly. Next, a behavior of an integer k, represents the planet's under attack
number. The next k lines, each line has an integer, in the order listed the targets Imperial Army. This number k different from each other and are 0 to n-1 norm
Around inside.

[Output]

The first row is the number of blocks communicated at the beginning of the planet. The next K lines of an integer, indicates the time after the planet against existing
communication the number of blocks.

Sample Input
8 13 
0 1 
1 6 
6 5 
5 0 
0 6 
1 2 
2 3
3 4
4 5 
7 1 
7 2 
7 6 
3 6 
5 
1 
6 
3 
5 
7
Sample Output 1
1
1
2
3
3

 

Meaning of the questions is very clear, after seeking removed several paths, leaving a few blocks Unicom. (If you have not read it, I give an example: Suppose we start Unicom case 1-2-3-4-5-6-7, suppose I blew up 4-5 this path, it becomes 1 -2-3-45-6-7 as 1,2,3,4 5,6,7 and mutually connected, so now there are two blocks Unicom)

Such a see FIG ah class path, the first thought disjoint-set.

The problem to Liao, here is to blow up the path, the path is deleted, we learned disjoint-set does not seem to delete, how to do?

Think about reverse thinking. We in turn become the construction of the path, disjoint-set can be achieved. That is not to blow up the road to repair it, then neatly solved.

The codes (o ゜ ▽ ゜) o ☆

 1 #include<iostream>
 2 #include<cstdio> 
 3 using namespace std;
 4 #define mx 400001
 5 int ans[mx],b[mx],bro[mx],head[mx],next[mx];
 6 int da[mx],db[mx],fa[mx];
 7 int num1=0;
 8 inline int read()  //一开始怕超时,加了快读(一种输入优化)
 9 {
10     int x=0,f=1;
11     char ch=getchar();
12     while (ch<'0'||ch>'9')
13     {
14         if(ch=='-')
15             f=-1;
16         ch=getchar();
17     }
18     while (ch>='0'&&ch<='9')
19     {
20         x=(x<<1)+(x<<3)+(ch^48);
21         ch=getchar();
22     }
23     return x*f;
24 }
25 void cn(int o,int p)  //用前向星来建图
26 {
27     num1++;
28     da[num1]=o;
29     db[num1]=p;
30     next[num1]=head[o];
31     head[o]=num1;
32 }
33 int fd(int o)  //并查集の查找函数
34 {
35     if (fa[o]==o) 
36        return o;
37     else return fa[o]=fd(fa[o]);
38 }
39 int main()
40 {
41     int i,num,n,m,k;
42     n=read(); m=read();
43     for (i=0;i<=n;i++)
44     {
45           fa[i]=i;
46           head[i]=-1;
47     }
48     for (i=1;i<=m;i++)
49     {
50           int u,v;
51           u=read(); v=read();
52           cn(u,v); cn(v,u);
53     }
54     cin>>k;
55     for (i=1;i<=k;i++)
56     {
57           b[i]=read();
58           bro[b[i]]=1;
59     }
60     num=n-k;
61     for (i=1;i<=(2*m);i+=2)
62     {
63           if (bro[da[i]]==0 && bro[db[i]]==0 && fd(da[i])!=fd(db[i]))
64           {
65                  fa[fd(db[i])]=fd(da[i]);
66                  num--;
67           }
68     }
69     ans[k+1]=num;
70     for (i=k;i>=1;i--)  //这里一定要注意是倒过来的,自己理解理解
71     {
72           num++;
73           bro[b[i]]=0;
74           int j=head[b[i]];
75           while (j>-1)
76           {
77                 if (bro[db[j]]==0 && fd(b[i])!=fd(db[j]))
78                 {
79                        num--;
80                        fa[fd(db[j])]=fd(b[i]);
81                 }                
82             j=next[j];
83           }
84           ans[i]=num;        
85     }
86     for (i=1;i<=(k+1);i++)
87         printf("%d\n",ans[i]);
88     return 0;
89 }

 

 

 

Guess you like

Origin www.cnblogs.com/lord-jiong/p/11295162.html