SCOI2010游戏

发现这题的并查集做法真是惊呆了

不过似乎匹配跑得更快?

对于一个联通块,假如不含环(就是一棵树),那么必定可以满足其中任意的p-1个点。

对于一个联通块,假如含环,那么必定全部的p个点都能满足。

那么合并并查集的时候可以利用一个vis来维护这个性质

把权值看成点,把武器看成边

如果每次加入的边是合并两个联通块

就把权值小的联通块并到权值大的联通块,然后给权值小的vis=true

如果不是

就把改联通块的顶点的vis=true

这样就可以保证,如果一个大小为N联通块

=N-1条边构成,最大点的vis=false,其他为true

≥N条边构成,所有点的vis=true

然后最后只要一次扫描vis就可以得出答案了 ————hzwer

代码:

 1 var i,n,m,x,y,tmp:longint;
 2     fa:array[0..15000] of longint;
 3     vis:array[0..15000] of boolean;
 4 function find(x:longint):longint;
 5  begin
 6  if fa[x]<>x then fa[x]:=find(fa[x]);
 7  exit(fa[x]);
 8  end;
 9 procedure main;
10  begin
11  readln(n);
12  fillchar(vis,sizeof(vis),false);
13  for i:=1 to 10100 do fa[i]:=i;
14  for i:=1 to n do
15   begin
16   readln(x,y);
17   x:=find(x);y:=find(y);
18   if x=y then vis[x]:=true
19   else
20     begin
21       if x>y then begin tmp:=x;x:=y;y:=tmp;end;
22       fa[x]:=y;
23       vis[x]:=true;
24     end;
25   end;
26  for i:=1 to 10010 do if (not(vis[i])) and (find(i)=i) then break;
27  writeln(i-1);
28  end;
29 begin
30  main;
31 end.      
View Code
原文地址:https://www.cnblogs.com/zyfzyf/p/3800620.html