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.