【NOIP2017练习&BZOJ4998】星球联盟(强联通分量,并查集)

题意:

在遥远的S星系中一共有N个星球,编号为1…N。其中的一些星球决定组成联盟,以方便相互间的交流。

但是,组成联盟的首要条件就是交通条件。初始时,在这N个星球间有M条太空隧道。每条太空隧道连接两个星球,使得它们能够相互到达。若两个星球属于同一个联盟,则必须存在一条环形线路经过这两个星球,即两个星球间存在两条没有公共隧道的路径。

为了壮大联盟的队伍,这些星球将建设P条新的太空隧道。这P条新隧道将按顺序依次建成。一条新轨道建成后,可能会使一些星球属于同一个联盟。你的任务是计算出,在一条新隧道建设完毕后,判断这条新轨道连接的两个星球是否属于同一个联盟,如果属于同一个联盟就计算出这个联盟中有多少个星球。

对于100%的数据有1≤N,M,P≤200000。

思路:

据说还可以用LCT+并查集维护连通性与size大小

 1 var q,fa,size,f,a,b,c,h,head,vet,next,x,y:array[1..1100000]of longint;
 2     n,m,p,i,j,u,e,v,t,tot,z,w:longint;
 3 
 4 procedure add(a,b:longint);
 5 begin
 6  inc(tot);
 7  next[tot]:=head[a];
 8  vet[tot]:=b;
 9  head[a]:=tot;
10 end;
11 
12 function find(k:longint):longint;
13 begin
14  if k=f[k] then exit(k);
15  f[k]:=find(f[k]);
16  exit(f[k]);
17 end;
18 
19 function lca(x,y:longint):longint;
20 var t:longint;
21 begin
22  x:=find(x); y:=find(y);
23  if x=y then exit(x);
24  if h[x]>h[y] then
25  begin
26   t:=lca(fa[x],y); size[t]:=size[t]+size[x]; f[x]:=f[t];
27  end;
28  if h[x]<=h[y] then
29  begin
30   t:=lca(fa[y],x); size[t]:=size[t]+size[y]; f[y]:=f[t];
31  end;
32  exit(t);
33 end;
34 
35 begin
36  assign(input,'bzoj4998.in'); reset(input);
37  assign(output,'bzoj4998.out'); rewrite(output);
38  readln(n,m,p);
39  for i:=1 to m do read(x[i],y[i]);
40  for i:=1 to p do
41  begin
42   read(x[m+i],y[m+i]);
43   b[m+i]:=1;
44  end;
45  m:=m+p;
46  for i:=1 to n do f[i]:=i;
47  for i:=1 to m do
48  begin
49   u:=x[i]; v:=y[i];
50   if find(u)=find(v) then continue;
51   f[f[u]]:=f[v]; c[i]:=1;
52   add(u,v); add(v,u);
53  end;
54  for i:=1 to n do
55  begin
56   if h[i]>0 then continue;
57   t:=0; w:=1; q[1]:=i; h[i]:=1;
58   while t<w do
59   begin
60    inc(t); u:=q[t];
61    e:=head[u];
62    while e<>0 do
63    begin
64     v:=vet[e];
65     if h[v]=0 then
66     begin
67      inc(w); q[w]:=v; h[v]:=h[u]+1; fa[v]:=u;
68     end;
69     e:=next[e];
70    end;
71   end;
72  end;
73  for i:=1 to n do
74  begin
75   f[i]:=i; size[i]:=1;
76  end;
77  //for i:=1 to n do writeln(h[i]);
78  //for i:=1 to m do writeln(c[i]);
79  for i:=1 to m do
80  begin
81   if c[i]=1 then
82   begin
83    if b[i]=1 then writeln('No');
84    continue;
85   end;
86   z:=lca(x[i],y[i]);
87  // writeln(z);
88   if b[i]=1 then writeln(size[z]);
89  end;
90 
91 
92  close(input);
93  close(output);
94 end.

 

posted on 2017-07-13 19:49  myx12345  阅读(244)  评论(0编辑  收藏  举报

导航