题解 P1807 【最长路_NOI导刊2010提高(07)】

· · 题解

这道题可以用拓扑排序做,但是要注意的一个地方就是要对数据预处理一下。根据题目,找出从1到n的最长路,那么我们要预处理掉1以外其他入度为0的点,以及除去它们之后衍生出来的入度为0的点......否则,将会对后面的拓扑排序造成影响,具体怎么影响的就是有的点可能除不干净入度。可以用BFS实现。状态转移方程f[j]:=max(f[j],f[i]+v[i,j])(f[j]:1-j的最长路径)。

附Pascal代码(里面有一些很奇怪的没用的地方,属于我看不懂题目而加的保险,请自行判断去留):

program foodweb;
const maxn=1501;
      maxm=50001;
var h,d,f,q:array[1..maxn] of longint;
    v,next,w:array[1..maxm] of longint;
    i,j,k,p,n,m,l,hd,tl,s,nt:longint;
function mx(a,b:longint):longint;
begin
    if a>b then exit(a) else exit(b);
end;
procedure swap;
begin
    if i=j then exit;
    i:=i xor j;
    j:=i xor j;
    i:=i xor j;
end;
begin
    read(n,m);
    fillchar(f,sizeof(f),0);
    fillchar(d,sizeof(d),0);
    fillchar(h,sizeof(h),0);
    p:=0;

    for k:=1 to m do
    begin
        read(i,j,l);
        inc(p);
        if i>=j then swap;
        v[p]:=j;
        w[p]:=l;
        inc(d[j]);
        next[p]:=h[i];
        h[i]:=p;
    end;
    f[n]:=-1;
    hd:=0;tl:=0;
    for i:=2 to n do
    begin
        if d[i]=0 then
        begin
            inc(tl);
            q[tl]:=i;
        end;
    end;
    while hd<tl do
    begin
        inc(hd);
        s:=q[hd];
        nt:=h[s];
        while nt>0 do
        begin
            dec(d[v[nt]]);
            if d[v[nt]]=0 then
            begin
                inc(tl);
                q[tl]:=v[nt];
            end;
            nt:=next[nt];
        end;
    end;
    hd:=0;tl:=0;

    inc(tl);
    q[tl]:=1;
    while hd<tl do
    begin
        inc(hd);
        s:=q[hd];
        nt:=h[s];
        while nt>0 do
        begin
            dec(d[v[nt]]);
            if d[v[nt]]=0 then
            begin
                inc(tl);
                q[tl]:=v[nt];
            end;
            f[v[nt]]:=mx(f[v[nt]],f[s]+w[nt]);
            nt:=next[nt];
        end;
    end;
    writeln(f[n]);
end.