【图论】【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.
反思
对经典算法的改进一定是建立在对算法的深刻理解之上!