并查集--CSUOJ 1601 War

并查集的经典题目:

CSUOJ 1601: War

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit:
247  Solved: 70
[Submit][Status][Web
Board
]

Description

AME decided to destroy CH’s country. In CH’ country, There are N villages,
which are numbered from 1 to N. We say two village A and B are connected, if and
only if there is a road between A and B, or there exists a village C such that
there is a road between A and C, and C and B are connected. To defend the
country from the attack of AME, CH has decided to build some roads between some
villages. Let us say that two villages belong to the same garrison area if they
are connected.
Now AME has already worked out the overall plan including
which road and in which order would be attacked and destroyed. CH wants to know
the number of garrison areas in his country after each of AME’s attack.

Input

The first line contains two integers N and M — the number of villages and
roads, (2 ≤ N ≤ 100000; 1 ≤ M ≤ 100000). Each of the next M lines contains two
different integers u, v (1<=u, v<=N)—which means there is a road between u
and v. The next line contains an integer Q which denotes the quantity of roads
AME wants to destroy (1 ≤ Q ≤ M). The last line contains a series of numbers
each of which denoting a road as its order of appearance — different integers
separated by spaces.

Output

Output Q integers — the number of garrison areas in CH’s country after each
of AME‘s attack. Each pair of numbers are separated by a single space.

Sample Input

3 1
1 2
1
1
4 4
1 2
2 3
1 3
3 4
3
2 4 3

Sample Output

3
1 2 3
 1 /*题目大意:n个点m条边(边1,边2...边m),q个要摧毁的边,求按顺序每摧毁一条边后图中连通块的个数
 2
 3
 4
 5 题目分析:并查集,先找出最后状态,反向加边,先将q条路全部摧毁后的连通块个数求出来,然后加边即可,每加一条边,用并查集判断,若两点不在同一连通块中,则合并且连通块个数减1*/
 6 #include<cstdio>
 7 #include<cstring>
 8 #define N 100100
 9 struct Edge {
10     int u,v;
11 }edge[N];
12 bool visited[N];
13 int a[N],stack[N];
14 int n,m,q,ans=0;
15 int father[N];
16 int find(int x)
17 {
18     return (father[x]==x)?father[x]:father[x]=find(father[x]);/*注意路径压缩和返回father[x]*/
19 }
20 void add_tu()
21 {
22     for(int i=1;i<=n;++i)
23     father[i]=i;
24     for(int i=1;i<=m;++i)
25     {
26         if(visited[i]) continue;
27         int r1=find(edge[i].u);
28         int r2=find(edge[i].v);
29         if(r1!=r2)
30         {
31             father[r2]=r1;
32             ans--;/*先把连通块的数目设为n,建图的过程中,边建边删除,也可以统计father[i]==i*/
33         }
34     }
35     stack[q]=ans;/*当前的状态是q的状态,不能加边了*/
36 }
37 void add_edge()
38 {
39     for(int i=q-1;i>=1;--i)
40     {
41         int r1=find(edge[a[i+1]].u);/*注意加的这一条边是当前状态的后一条边,因为这个后一条边没有删除,而不是a[i],之前深受其害,连样例都过了*/
42         int r2=find(edge[a[i+1]].v);
43         if(r1!=r2)
44         {
45             father[r2]=r1;
46             ans--;
47
48         }
49         stack[i]=ans;/*注意不要把这句放到if里面*/
50     }
51 }
52 int main()
53 {
54     while(scanf("%d%d",&n,&m)!=EOF)/*注意这里不能只用scanf("%d%d",&n,&m),因为这样没法用^z结束程序*/
55         memset(edge,0,sizeof(edge));
56         memset(visited,false,sizeof(visited));/*别忘记初始化*/
57         memset(a,0,sizeof(a));
58         memset(stack,0,sizeof(stack));
59         ans=n;
60         for(int i=1;i<=m;++i)
61         {
62             scanf("%d%d",&edge[i].u,&edge[i].v);
63         }
64         scanf("%d",&q);
65         for(int i=1;i<=q;++i)
66         {
67             scanf("%d",&a[i]);
68             visited[a[i]]=true;/*把不访问的边设上标记*/
69         }
70         add_tu();
71         add_edge();
72         for(int i=1;i<=q-1;++i)
73         printf("%d ",stack[i]);/*CSUOJ这个坑爹的OJ,多输出一个空格,就格式不对*/
74         printf("%d\n",stack[q]);
75     }
76     return 0;
77 }
 
时间: 2024-11-04 22:23:08

并查集--CSUOJ 1601 War的相关文章

CSUOJ 1601 War (离线并查集求连通块个数)

1601: War Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 130  Solved: 38 [Submit][Status][Web Board] Description AME decided to destroy CH's country. In CH' country, There are N villages, which are numbered from 1 to N. We say two village A and B ar

CSU 1601 War (并查集)

1601: War Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 202  Solved: 58 [Submit][Status][Web Board] Description AME decided to destroy CH's country. In CH' country, There are N villages, which are numbered from 1 to N. We say two village A and B ar

csu 1601: War(并查集求每次去掉一条边后连通分量的个数)

1601: War Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 85  Solved: 25 [Submit][Status][Web Board] Description AME decided to destroy CH's country. In CH' country, There are N villages, which are numbered from 1 to N. We say two village A and B are

ZOJ 3261 - Connections in Galaxy War ,并查集删边

In order to strengthen the defense ability, many stars in galaxy allied together and built many bidirectional tunnels to exchange messages. However, when the Galaxy War began, some tunnels were destroyed by the monsters from another dimension. Then m

ZOJ 3261 Connections in Galaxy War (并查集)

Connections in Galaxy War Time Limit: 3 Seconds      Memory Limit: 32768 KB In order to strengthen the defense ability, many stars in galaxy allied together and built many bidirectional tunnels to exchange messages. However, when the Galaxy War began

UVA 10158 War(并查集)

War A war is being lead between two countries, A and B. As a loyal citizen of C, you decide to help your country's espionage by attending the peace-talks taking place these days (incognito, of course). There are n people at the talks (not including y

题解报告:zoj 3261 Connections in Galaxy War(离线并查集)

Description In order to strengthen the defense ability, many stars in galaxy allied together and built many bidirectional tunnels to exchange messages. However, when the Galaxy War began, some tunnels were destroyed by the monsters from another dimen

CSU1601: War(并查集)

1601: War Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 82  Solved: 24 [Submit][Status][Web Board] Description AME decided to destroy CH's country. In CH' country, There are N villages, which are numbered from 1 to N. We say two village A and B are

zoj 3261 Connections in Galaxy War(并查集+离线逆向操作)

 题目:给出一些点,每个点有权值,然后有一些边,相连.无向的.然后有一些操作 query a.表示从a出发的能到达的所有点权值最大的点的编号(相同取编号最小,而且权值要比自己大) destory a,b 表示删除连接a,b的边 思路并查集,但是要逆向处理,所以先离线读入,从后向前处理,于是对于destroy操作,等价于连接两个点的操作,然后对于每个询问输出即可 #include<cstdio> #include<cstring> #include<cmath> #i