洛谷 P1462 通往奥格瑞玛的道路

来源:互联网 发布:怎么屏蔽网络监控 编辑:程序博客网 时间:2024/04/28 02:21

  • 题目
  • 题解
  • 代码

题目

在艾泽拉斯,有n个城市。编号为1,2,3,…,n。

城市之间有m条双向的公路,连接着两个城市,从某个城市到另一个城市,会遭到联盟的攻击,进而损失一定的血量。

每次经过一个城市,都会被收取一定的过路费(包括起点和终点)。路上并没有收费站。

假设1为暴风城,n为奥格瑞玛,而他的血量最多为b,出发时他的血量是满的。

歪嘴哦不希望花很多钱,他想知道,在可以到达奥格瑞玛的情况下,他所经过的所有城市中最多的一次收取的费用的最小值是多少。

对于60%的数据,满足n≤200,m≤10000,b≤200
对于100%的数据,满足n≤10000,m≤50000,b≤1000000000
对于100%的数据,满足ci≤1000000000,fi≤1000000000,可能有两条边连接着相同的城市。

题解

歪嘴哦这个倒霉的孩子居然同时具有血量和过路费,两个代价,怎么办?于是考虑先确定一个值。确定过路费后,发现剩下的问题就是最短路,于是果断SPFA

那么怎么确定过路费呢?
考虑到题目要求“他所经过的所有城市中最多的一次收取的费用的最小值是多少”,于是可以看成求最大值里的最小值。这个嘛,最大值里的最小值,最小值里的最大值,统统果断二分。
二分答案,然后用SPFA判断当前答案是否行得通。

然而提交了

24
次都没有对

最后发现错的是什么地方呢,读入!
这个故事告诉我们哪怕是读入也可以让你的正确率暴跌

时间复杂度O(m log n)

代码

var  n,m,b,i,j,k,l,r,mid:longint;  a:array[1..100000,1..4]of longint;  s,w,c:array[0..10000]of longint;  ls:array[1..100000]of longint;  v:array[1..1000000]of longint;  d:array[1..50000]of boolean;function spfa(key:longint):boolean;var  l,r,i,j,k,t:longint;begin  for i:=1 to n do    s[i]:=1000000000;  fillchar(d,sizeof(d),true);  l:=0;r:=1;v[r]:=1;s[1]:=0;d[1]:=false;  while l<r do    begin      inc(l);      i:=ls[v[l]];      while i>0 do        begin          if c[a[i,1]]>key then            begin              i:=a[i,4];              continue;            end;          if (s[a[i,1]]+a[i,3]<=b)and(s[a[i,1]]+a[i,3]<=s[a[i,2]]) then            begin              s[a[i,2]]:=s[a[i,1]]+a[i,3];              if d[a[i,2]] then                begin                  inc(r);                  v[r]:=a[i,2];                  d[a[i,2]]:=false;                end;            end;          i:=a[i,4];        end;      d[v[l]]:=true;    end;  if s[n]<=b then exit(true) else exit(false);end;procedure qsort(l,r:longint);var  i,j,key,t:longint;begin  if l>=r then exit;  i:=l;j:=r;  key:=w[(l+r) div 2];  repeat    while w[i]<key do inc(i);    while w[j]>key do dec(j);    if i<=j then      begin        t:=w[i];w[i]:=w[j];w[j]:=t;        inc(i);dec(j);      end;  until i>j;  qsort(i,r);  qsort(l,j);end;begin  readln(n,m,b);  for i:=1 to n do    begin      readln(w[i]);      if w[i]>j then begin j:=w[i];r:=i;end;    end;  k:=w[1];if w[n]>k then k:=w[n];  c:=w;  qsort(1,n);  j:=0;  for i:=1 to m do    begin      inc(j);      readln(a[j,1],a[j,2],a[j,3]);          a[j,4]:=ls[a[j,1]];ls[a[j,1]]:=j;          inc(j);          a[j,1]:=a[j-1,2];a[j,2]:=a[j-1,1];a[j,3]:=a[j-1,3];          a[j,4]:=ls[a[j-1,2]];ls[a[j-1,2]]:=j;    end;  if not(spfa(w[n])) then begin writeln('AFK');halt;end;  l:=1;r:=n;  while l<r do    begin      mid:=(l+r) div 2;      if (k>w[mid]) or not(spfa(w[mid])) then l:=mid+1 else r:=mid;    end;  if spfa(w[l]) then  writeln(w[l])  else writeln(w[r]);end.
1 0
原创粉丝点击