现在的位置: 首页 > 综合 > 正文

tyvj1031热浪——初学spfa

2013年05月01日 ⁄ 综合 ⁄ 共 2474字 ⁄ 字号 评论关闭

背景 Background

USACO OCT09 9TH

描述 Description

德克萨斯纯朴的民眾们这个夏天正在遭受巨大的热浪!!!他们的德克萨斯长角牛吃起来不错,可是他们并不是很擅长生產富含奶油的乳製品。Farmer John此时以先天下之忧而忧,后天下之乐而乐的精神,身先士卒地承担起向德克萨斯运送大量的营养冰凉的牛奶的重任,以减轻德克萨斯人忍受酷暑的痛苦。
FJ已经研究过可以把牛奶从威斯康星运送到德克萨斯州的路线。这些路线包括起始点和终点先一共经过T (1 <= T <= 2,500)个城镇,方便地标号為1到T。除了起点和终点外地每个城镇由两条双向道路连向至少两个其它地城镇。每条道路有一个通过费用(包括油费,过路费等等)。考虑这个有7个城镇的地图。城镇5是奶源,城镇4是终点(括号内的数字是道路的通过费用)。
经过路线5-6-3-4总共需要花费3 (5->6) + 4 (6->3) + 3 (3->4) = 10的费用。
给定一个地图,包含C (1 <= C <= 6,200)条直接连接2个城镇的道路。每条道路由道路的起点Rs,终点Re (1 <= Rs <= T; 1 <= Re <= T),和花费(1 <= Ci <= 1,000)组成。求从起始的城镇Ts (1 <= Ts <= T)到终点的城镇Te(1 <= Te <= T)最小的总费用。

输入格式 Input Format

* 第一行: 4个由空格隔开的整数: T, C, Ts, Te
* 第2到第C+1行: 第i+1行描述第i条道路。有3个由空格隔开的整数: Rs, Re和Ci

输出格式 Output Format

* 第一行: 一个单独的整数表示Ts到Te的最短路的长度。(不是费用麼?怎麼突然变直白了
——译者注)数据保证至少存在一条道路。

样例输入 Sample Input

7 11 5 4

2 4 2

1 4 3

7 2 2

3 4 3

5 7 5

7 3 3

6 1 1

6 3 4

2 4 3

5 6 3

7 2 1

样例输出 Sample Output

7

时间限制 Time Limitation

各个测试点1s

注释 Hint

5->6->1->4 (3 + 1 + 3)

分析:

显然的最短路问题,很早之前我用dijstra过了,

现在初学spfa,来拿它练练手,基础算法,不解释了。。。

dijstra:

program ty_1031;
  var
    i,j,n,m,t,k,l,ss,s,cc,c,ee,e,min,minn:longint;
    a:array[1..2500,1..2500]of longint;
    b:array[1..2500]of integer;
  begin
    assign(input,'ty.in');
    reset(input);
    readln(t,c,ss,ee);
    filldword(a,sizeof(a)div 4,maxint);
    for i:=1 to c do
      begin
        readln(s,e,cc);
        if cc< a[s,e] then
          begin
            a[s,e]:=cc;
            a[e,s]:=cc;
          end;
      end;
    minn:=ss;b[ss]:=1;
    for k:=2 to t do
      begin
        min:=maxlongint;
        for i:=1 to t do
          if (a[ss,i]<min)and(b[i]=0) then
            begin
              min:=a[ss,i];
              minn:=i;
            end;
        b[minn]:=1;
        for j:=1 to t do
          if (j<>minn)and(a[ss,minn]+a[minn,j]<a[ss,j])and(b[j]=0) then
            a[ss,j]:=a[ss,minn]+a[minn,j];
      end;
    writeln(a[ss,ee]);
    close(input);
  end.

spfa:

program ty_1031_2;
  var
    i,j,n,m,k,l,num,st,en,x,y,z,zz,head,tail,nn:longint;
    a:array[0..20000]of record
      f,t,val,next:longint;
    end;
    b,d:array[1..20000]of longint;
    q:array[1..100000]of longint;
  begin
    assign(input,'ty.in');
    reset(input);
    readln(n,m,st,en);
    num:=3000;
    for i:=1 to m do
      begin
        read(x,y,z);
        if a[x].val=0 then begin a[x].t:=y;a[x].val:=z;a[x].f:=x;end
          else begin
            zz:=x;
            while a[zz].next<>0 do zz:=a[zz].next;
            inc(num);
            a[zz].next:=num;
            a[num].val:=z;
            a[num].f:=x;
            a[num].t:=y;
          end;
        if a[y].val=0 then begin a[y].t:=x;a[y].val:=z;a[y].f:=y;end
          else begin
            zz:=y;
            while a[zz].next<>0 do zz:=a[zz].next;
            inc(num);
            a[zz].next:=num;
            a[num].val:=z;
            a[num].f:=y;
            a[num].t:=x;
          end;
      end;
    fillchar(d,sizeof(d),10);
    head:=1;tail:=1;b[st]:=1;
    q[1]:=st;d[st]:=0;
    while head<>tail+1 do
      begin
        nn:=q[head];
        repeat
          if (a[nn].val+d[a[nn].f]<d[a[nn].t])then
            begin
              d[a[nn].t]:=a[nn].val+d[a[nn].f];
              if b[a[nn].t]=0 then
                begin
                  b[a[nn].t]:=1;
                  inc(tail);
                  if tail=100000 then tail:=1;
                  q[tail]:=a[nn].t;
                end;
            end;
          nn:=a[nn].next;
        until nn=0;
        b[q[head]]:=0;
        inc(head);
        if head=100000 then tail:=1;
      end;
    writeln(d[en]);
    close(input);
  end.

抱歉!评论已关闭.