混合图 (Standard IO)

Description

有一张N个点,M1条有向边,M2条无向边组成的混合图。询问一个给所有无向边定向的方案。使得最终的图中没有环。保证一定有解。

Input

第一行,三个数字N,M1,M2。
接下来M1+M2行,每行两数字Ai,Bi。表示一条边。
前M1条是有向边。方向是Ai到Bi。

Output

输出M2行,按输出顺序输出为无向边确定的方向。Ai Bi或Bi Ai。
有多解时输出任意解。

题解

对原图做拓扑排序,得到每个点的入队时间,加边的时候把边定向为从入队时间早的点到晚的点,原来的入队顺序就依然成立,就无环了。

代码

type
  arr=record
        y,next:longint;
      end;
var
  n,nm,m1,m2:longint;
  e:array [0..400001] of arr;
  ls,f,q,b,h:array [0..200001] of longint;

procedure add(x,y:longint);
begin
  inc(nm);
  e[nm].y:=y;
  e[nm].next:=ls[x];
  ls[x]:=nm;
end;

procedure topsort;
var
  he,ta,i,t,v:longint;
begin
  he:=1; ta:=0;
  for i:=1 to n do
    if f[i]=0 then
      begin
        inc(ta);
        q[ta]:=i; b[i]:=1;
      end;
  while he<=ta do
    begin
      t:=q[he];
      i:=ls[t];
      while i<>0 do
        begin
          v:=e[i].y;
          dec(f[v]);
          if f[v]=0 then
            begin
              inc(ta);
              q[ta]:=v; b[v]:=1;
            end;
          i:=e[i].next;
        end;
      inc(he);
    end;
end;

procedure init;
var
  i,u,v:longint;
begin
  readln(n,m1,m2);
  nm:=0;
  for i:=1 to m1 do
    begin
      readln(u,v);
      add(u,v);
      inc(f[v]);
    end;
  topsort;
  for i:=1 to n do
    h[q[i]]:=i;
  for i:=1 to m2 do
    begin
      readln(u,v);
      if h[u]<h[v] then writeln(u,' ',v)
                   else writeln(v,' ',u);
    end;

end;

begin
  init;
end.
原文地址:https://www.cnblogs.com/zyx-crying/p/9319587.html