poj 2492 A Bug's Life 并查集

题意:调查一种虫子的性行为,先假定虫子里没有同性恋。每一次测试输入N只虫,然后输入M个数对( x, y ),表示 x, y 之间有性行为, 最后判断假设成立与否(即判断有没有同性恋)。

分析:这题的题目好污啊,看得我都羞羞了~~

恩如果你脑袋里装的还是那些东西的话我建议你过一会再来看。

首先我们假设虫子里没有同性恋,也就是说若虫子1与虫子2、3有关系则2和3必为同性且和1为异性,那么就可以把2和3进行合并,这里合并用到的是并查集,时间复杂度只有O(1),不会的自己去网上找资料。也就是说把所有和某条虫发生过关系的虫子全部合并。最后我们来判断:若假设不成立也就是没有同性恋,那么任意发生过关系的两条虫一定会在两个不同的集合内,若不满足这一项,则说明这里面有同性恋。

代码:

var
  l,t,n,m,x,y,i:longint;
  a:array[0..2000000,1..2] of longint;
  f:array[1..2000] of longint;
  flag:boolean;

procedure qsort(l,r:longint);
var
  i,j,k:longint;
begin
  if l>=r then exit;
  i:=l;
  j:=r;
  k:=a[(i+j) div 2,1];
  repeat
    while a[i,1]<k do inc(i);
    while a[j,1]>k do dec(j);
    if i<=j then
    begin
      a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];
      inc(i);dec(j);
    end;
  until i>j;
  qsort(i,r);
  qsort(l,j);
end;

function find(x:longint):longint;
begin
  if f[x]=x then exit(x);
  find:=find(f[x]);
  f[x]:=find;
end;

begin
  readln(t);
  for l:=1 to t do
  begin
    if l>1 then writeln;
    writeln('Scenario #',l,':');
    readln(n,m);
    for i:=1 to m do
    begin
      readln(x,y);
      a[i*2-1,1]:=x;
      a[i*2-1,2]:=y;
      a[i*2,1]:=y;
      a[i*2,2]:=x;
    end;
    qsort(1,m*2);
    a[0,1]:=0;
    for i:=1 to n do
      f[i]:=i;
    for i:=1 to m*2 do
      if a[i,1]<>a[i-1,1]
        then x:=a[i,2]
        else if find(a[i,2])<>find(x) then f[find(a[i,2])]:=find(x);
    flag:=true;
    for i:=1 to m*2 do
      if find(a[i,1])=find(a[i,2]) then
      begin
        writeln('Suspicious bugs found!');
        flag:=false;
        break;
      end;
    if flag then writeln('No suspicious bugs found!');
  end;
end.


你可能感兴趣的:(poj 2492 A Bug's Life 并查集)