【图论】【poj 1094】Sorting It All Out

问题

给定多组数据,每组数据中有多个大小关系,让你判断是否能产生一个拓扑序列,如果可以,输出在第几个关系之后得到,并输出这个序列。如果不可以,输出在第几个关系之后无解;如果存在多解,按题目要求输出。

分析

就是拓扑排序,加队列优化,再加一点改进。每次读入关系之后进行拓扑排序。我们知道,如果一个序列能得到拓扑排序的序列,那么在每步有且仅有一个节点的入度为0,如果不存在入度为零的点,则无解。如果入度为零的点的个数多于一个,则存在多解。

对于队列拓扑排序的原理我们了解,每次选取队首元素是,判断当前队伍中元素的个数,如果多于一个,暂时标记多解(可能在后面的过程中出现无解)。那么什么时候队列中不在有元素捏?就是停止while循环的时候,所以我们只需在最后判断是否生成一个长度为n的序列即可(如果存在多解,同样可以生成,想想为什么)。

code

program liukee;
var
  a:array[1..50,0..50] of longint;
  into,into1:array[1..50] of longint;
  ans:array[1..1000] of longint;
  n,m,i,x,y,turn,temp,j:longint;
  flag:boolean;
  ch1,ch2,kong:char;

function spfa:longint;
var
  l,r,now,sum,i,tt:longint;
  q:array[1..100000] of longint;
begin
  spfa:=1;
  fillchar(q,sizeof(q),0);
  fillchar(ans,sizeof(ans),0);
  l:=0;
  r:=0;
  tt:=0;
  for i:=1 to n do
    if into1[i]=0 then
	begin
	  inc(r);
	  q[r]:=i;
	end;
  while l<r do
  begin
    sum:=r-l;
    if sum>1 then spfa:=-1;
	inc(l);
	now:=q[l];
	inc(tt);
	ans[tt]:=now;
	for i:=1 to a[now,0] do
	begin
	  dec(into1[a[now,i]]);
	  if into1[a[now,i]]=0 then
	  begin
	    inc(r);
        q[r]:=a[now,i];
	  end;
    end;
  end;
  if tt<n then exit(0);
end;

begin
  readln(n,m);
  while (n<>0)and(m<>0)do
  begin
    flag:=false;
    fillchar(a,sizeof(a),0);
    fillchar(into,sizeof(into),0);
	turn:=0;
    for i:=1 to m do
	begin
	  inc(turn);
	  read(ch1);
	  x:=ord(ch1)-64;
	  read(kong);
	  read(ch2);
      readln;
	  y:=ord(ch2)-64;
	  inc(a[x,0]);
	  a[x,a[x,0]]:=y;
	  inc(into[y]);
	  if flag then continue;
	  into1:=into;
	  temp:=spfa;
	  if temp=1 then begin write('Sorted sequence determined after ',turn,' relations: ');flag:=true; for j:=1 to n do write(chr(ans[j]+64)); end
	  else if temp=0 then begin write('Inconsistency found after ',turn,' relations');flag:=true;end;
	end;
	if not flag then write('Sorted sequence cannot be determined');
    readln(n,m);
    write('.');
    writeln;
  end;
end.

反思

对经典算法的改进一定是建立在对算法的深刻理解之上!

posted @ 2011-03-06 19:07  liukee  阅读(353)  评论(0编辑  收藏  举报