题意:有一张N点M边的有向图,求最小的K使根据前K条边就能够确定图是否有唯一的拓扑序,
若没有唯一拓扑序输出-1
思路:二分答案再拓扑排序,以入度为0的节点作为新的一层,若某一层的节点个数<>1则没有唯一拓扑序
1 var head,vet,next,d,x,y,b:array[1..210000]of longint; 2 n,m,i,l,r,mid,last,tot:longint; 3 4 procedure add(a,b:longint); 5 begin 6 inc(tot); 7 next[tot]:=head[a]; 8 vet[tot]:=b; 9 head[a]:=tot; 10 end; 11 12 function isok(len:longint):boolean; 13 var s,e,i,st,v:longint; 14 begin 15 fillchar(head,sizeof(head),0); 16 fillchar(b,sizeof(b),0); 17 fillchar(d,sizeof(d),0); 18 tot:=0; 19 for i:=1 to len do 20 begin 21 add(x[i],y[i]); 22 inc(d[y[i]]); 23 end; 24 s:=0; 25 for i:=1 to n do 26 if d[i]=0 then begin st:=i; b[i]:=1; inc(s); end; 27 if s<>1 then exit(false); 28 for i:=1 to n-1 do 29 begin 30 e:=head[st]; 31 while e<>0 do 32 begin 33 v:=vet[e]; 34 dec(d[v]); 35 e:=next[e]; 36 end; 37 e:=head[st]; s:=0; 38 while e<>0 do 39 begin 40 v:=vet[e]; 41 if (d[v]=0)and(b[v]=0) then 42 begin 43 inc(s); b[v]:=1; st:=v; 44 end; 45 e:=next[e]; 46 end; 47 if s<>1 then exit(false); 48 end; 49 exit(true); 50 end; 51 52 begin 53 // assign(input,'cf645D.in'); reset(input); 54 // assign(output,'cf645D.out'); rewrite(output); 55 readln(n,m); 56 for i:=1 to m do readln(x[i],y[i]); 57 l:=1; r:=m; last:=m+1; 58 while l<=r do 59 begin 60 mid:=(l+r)>>1; 61 if isok(mid) then begin last:=mid; r:=mid-1; end 62 else l:=mid+1; 63 end; 64 if last=m+1 then writeln(-1) 65 else writeln(last); 66 //close(input); 67 // close(output); 68 end.