P1197 [JSOI2008] Star Wars

Topic description

Long ago, in a distant galaxy, a dark empire ruled the galaxy with its super weapons. One day, by chance, a rebel army destroyed the Empire's superweapons and captured almost all the planets in the galaxy. These planets are directly or indirectly connected to each other through special etheric tunnels.

But the good times didn't last long, and soon the Empire recreated his super weapon. With the power of this super weapon, the Empire began to systematically destroy the planets occupied by the rebels. Due to the continuous destruction of the planets, the communication channel between the two planets has also become unreliable. Now, the leader of the resistance army has given you a task: to give the connection of the ether tunnel between the original two planets and the order of the planets struck by the empire, and to find the connection block of the planet occupied by the resistance army after each strike as quickly as possible number of. (Two planets are in the same connectivity block if they can be connected directly or indirectly through an existing etheric channel).

Input and output format

Input format:

The first line of the input file contains two integers, N (1 <= N <= 2M) and M (1 <= M <= 200,000), representing the number of planets and the number of ether tunnels, respectively. Planets are numbered with integers from 0 to N-1.

The next M lines, each line includes two integers X, Y, where (0<=X<>Y<N), indicating that there is an ether tunnel between planet X and planet Y. Note that all ether tunnels are bidirectional.

The next line is an integer K, representing the number of planets the empire plans to hit.

The next K lines each have an integer X, which satisfies 0<=X<N, indicating the planet number that the empire plans to attack. Empires always destroy planets in the order they are entered.

Output format:

The first line of the output file is the number of connected blocks for the planet at the beginning.

The next K lines, each with an integer, represent the number of connected blocks of the existing planet after the blow.

Input and output example

Input example #1: 
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
1
2
3
3

illustrate

[JSOI2008]

 

Solution:

  This problem is easy to think of and check the set, but if the edges are added sequentially, it is difficult to count the points directly connected to the point and determine whether the connected block changes because the path compresses each time the point is deleted.

  正着不行就反向试试,此时考虑离线,逆向去加点并统计形成的连通块个数。

  那么每条边的修改顺序就是它所连两点中最晚被修改的时间,初始连通块个数为$tot=n$(即$n$个点),再按修改时间往前倒推去加边,每当形成新的连通块则连通块个数$tot-1$,则第$i$次修改时对应的答案为$tot-(k-i)$(即当前的连通块个数减去没有被删去的点个数),最后再倒序输出答案,就$OK$了。

  (貌似有点绕,看下代码就明了了~)

代码:

 

 1 // luogu-judger-enable-o2
 2 #include<bits/stdc++.h>
 3 #define il inline
 4 #define ll long long
 5 using namespace std;
 6 const int N=400005;
 7 int n,m,k,fa[N],tot,pos[N],ans[N];
 8 struct edge{
 9     int x,y,id;
10     bool operator <(edge a){return id<a.id;}
11 }a[N];
12 il int gi(){
13     int a=0;char x=getchar();bool f=0;
14     while((x<'0'||x>'9')&&x!='-')x=getchar();
15     if(x=='-')x=getchar(),f=1;
16     while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
17     return f?-a:a;
18 }
19 il int find(int x){if(x==fa[x])return x;return fa[x]=find(fa[x]);}
20 il void merge(int x,int y){x=find(x),y=find(y);if(x!=y)fa[x]=y,tot--;}
21 int main()
22 {
23     n=gi(),m=gi(),tot=n;
24     for(int i=0;i<=n;i++)fa[i]=i;
25     for(int i=1;i<=m;i++){
26         a[i].x=gi(),a[i].y=gi(),a[i].id=i;
27     }
28     k=gi();int op;
29     for(int i=k;i>=1;i--)op=gi(),pos[op]=i;
30     for(int i=1;i<=m;i++)a[i].id=max(pos[a[i].x],pos[a[i].y]);
31     sort(a+1,a+m+1);
32     op=1;
33     for(int i=0;i<=k;i++){
34         while(a[op].id==i){merge(a[op].x,a[op].y);op++;}
35         ans[i]=tot-(k-i);
36     }
37     while(k!=-1)printf("%d\n",ans[k--]);
38     return 0;
39 }

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324770961&siteId=291194637