HDU 4496 D-City(逆向并查集)

http://acm.hdu.edu.cn/showproblem.php?pid=4496

题意:

给出n个顶点m条边的图,每次选择一条边删去,求每次删边后的连通块个数。

思路:

离线处理删边,从后往前处理变成加边,用并查集维护连通块个数。其实这题和BZOJ 1015差不多。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 
 6 int n, m, tot, num;
 7 int p[10005], ans[100005], head[10005];
 8 
 9 struct node
10 {
11     int u,v;
12 }query[100005];
13 
14 struct edge
15 {
16     int v,next;
17 }e[200010];
18 
19 void addEdge(int u, int v)
20 {
21     e[tot].v = v;
22     e[tot].next = head[u];
23     head[u] = tot++;
24 }
25 
26 int finds(int x)
27 {
28     return p[x]==x?x:p[x]=finds(p[x]);
29 }
30 
31 void update(int u)
32 {
33     for(int i=head[u];i!=-1;i=e[i].next)
34     {
35         int v = e[i].v;
36         int x = finds(u);
37         int y = finds(v);
38         if(x!=y)  {p[x]=y;num--;}
39     }
40 }
41 
42 int main()
43 {
44     //freopen("in.txt","r",stdin);
45     while(~scanf("%d%d",&n,&m))
46     {
47         tot = 0;
48         memset(head,-1,sizeof(head));
49         for(int i=0;i<n;i++)  p[i]=i;
50         for(int i=1;i<=m;i++)
51             scanf("%d%d",&query[i].u,&query[i].v);
52 
53         num = n;
54         ans[m] = n;
55         for(int i=m;i>0;i--)
56         {
57             int u = query[i].u;
58             int v = query[i].v;
59             addEdge(u,v);
60             addEdge(v,u);
61             update(u);
62             update(v);
63             ans[i-1]=num;
64         }
65         for(int i=1;i<=m;i++)  printf("%d
",ans[i]);
66     }
67     return 0;
68 }
原文地址:https://www.cnblogs.com/zyb993963526/p/7886676.html