poj 3275 Ranking the Cows 传递闭包+邻接表优化

来源:互联网 发布:数据字典下载 编辑:程序博客网 时间:2024/06/05 06:58

题目大意

  FJ想按照奶牛产奶的能力给她们排序。现在已知有N头奶牛(1 ≤ N ≤ 1,000)。FJ通过比较,已经知道了M(1 ≤ M ≤10,000)对相对关系。每一对关系表示为“X Y”,意指X的产奶能力强于Y。现在FJ想要知道,他至少还要调查多少对关系才能完成整个排序。

 

分析

  如果排序可以确定了,就是任意两头牛之间的关系都可以确定了。N头奶牛一共有C(N, 2) = N * (N - 1) / 2对关系。由现在已知的关系如能确认K对关系,则要调查的次数就是C(N, 2) - K。

  那就变成了求有多少对点连通,用Floyd求传递闭包,但是n<=1000,用普通的Floyd会超时。思考一下就会发现,枚举中间节点K之后就开始枚举起点和终点I、J,若I与K,或者J与K之间根本就不联通,那么绝对无法松弛。所以说更高效的方式就是起点只检查能通向K的节点,终点只检查K能通向的节点,这样就会把复杂度大大降低。(用邻接表)

 

代码

const  maxv=10050;  maxe=1500;var  d,d1:array[1..maxe,0..maxv] of longint;  f:array[0..2000,0..2000] of boolean;  i,j,k,x,y:longint;  n,m:longint;  ans:longint;begin  read(n,m);  ans:=m;  for i:=1 to m do    begin      readln(x,y);      f[x,y]:=true;      d[x,0]:=d[x,0]+1;      d[x,d[x,0]]:=y;      d1[y,0]:=d1[y,0]+1;      d1[y,d1[y,0]]:=x;    end;  for k:=1 to n do    for i:=1 to d1[k,0] do      begin        x:=d1[k,i];        for j:=1 to d[k,0] do          begin            y:=d[k,j];            if not f[x,y]              then                begin                  d[x,0]:=d[x,0]+1;                  d[x,d[x,0]]:=y;                  d1[y,0]:=d1[y,0]+1;                  d1[y,d1[y,0]]:=x;                  f[x,y]:=true;                  ans:=ans+1;                end;          end;      end;  write(n*(n-1) div 2-ans);end.


1 0