zoukankan      html  css  js  c++  java
  • spfa专题

    SPFA专题

    1通往奥格瑞玛的道路

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

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

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

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

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

    输入输出格式

    输入格式:

    第一行3个正整数,nmb。分别表示有n个城市,m条公路,歪嘴哦的血量为b

    接下来有n行,每行1个正整数,fi。表示经过城市i,需要交费fi元。

    再接下来有m行,每行3个正整数,aibici(1<=aibi<=n)。表示城市ai和城市bi之间有一条公路,如果从城市ai到城市bi,或者从城市bi到城市ai,会损失ci的血量。

    输出格式:

    仅一个整数,表示歪嘴哦交费最多的一次的最小值。

    如果他无法到达奥格瑞玛,输出AFK

    输入输出样例

    输入样例#1 复制

    4 4 8

    8

    5

    6

    10

    2 1 2

    2 4 1

    1 3 4

    3 4 3

    输出样例#1 复制

    10

    说明

    对于60%的数据,满足n≤200m≤10000b≤200

    对于100%的数据,满足n≤10000m≤50000b≤1000000000

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

     

    最大值最小?二分答案。但有血量怎么办?因为你想要走到奥格瑞玛,你不能死,那血扣的最少的时候你还死了说明不可能通过,也就是AFK。所以这可以刚开始用一个很大的答案试试,如果能通过,说明可行。然后二分答案,这里要注意一个大大大坑,你快排了cost,它所对应的节点也就改变了,就是说通过i节点的费用不是原来的了。所以你需要一个临时数组来代替cost快排,然后将这个数组作为二分答案的数组。他们两两不干扰。要注意数组后效性

      1 var
      2 x,y,z,n,m,b,mi,sum,l,r,mid,blood,ma,ans:int64;
      3 a,w,cost,next,head,q,dis,c:array[0..200005]of int64;
      4 vis,bj:array[0..200005]of boolean;
      5 i,e:longint;
      6   procedure sort(l,r:int64);
      7       var
      8          i,j,x,y:int64;
      9       begin
     10          i:=l;
     11          j:=r;
     12          x:=c[(l+r) div 2];
     13          repeat
     14            while c[i]<x do
     15             inc(i);
     16            while x<c[j] do
     17             dec(j);
     18            if not(i>j) then
     19              begin
     20                 y:=c[i];
     21                 c[i]:=c[j];
     22                 c[j]:=y;
     23                 inc(i);dec(j);
     24              end;
     25          until i>j;
     26          if l<j then   sort(l,j);
     27          if i<r then   sort(i,r);
     28       end;
     29 
     30 procedure add(x,y,z:longint);
     31  begin
     32   inc(e);a[e]:=y;next[e]:=head[x];head[x]:=e;w[e]:=z;
     33  end;
     34  function check(mid:longint):boolean;
     35   var h,t,u,v,i:longint;
     36    begin
     37      h:=0;t:=1;
     38        fillchar(q,sizeof(q),0);
     39       fillchar(vis,sizeof(vis),false);
     40        fillchar(bj,sizeof(bj),false);
     41      q[1]:=1; vis[1]:=true;
     42     for i:=1 to n do dis[i]:=1<<30;
     43     for i:=1 to n do if mid<cost[i] then bj[i]:=true;
     44     dis[1]:=0;
     45       while h<t do
     46         begin
     47          inc(h);
     48          u:=q[h];
     49          i:=head[u];
     50          vis[u]:=false;
     51          while i>0 do
     52            begin
     53              v:=a[i];
     54           //   if mid=5 then writeln(u,' ',v);
     55               if (dis[u]+w[i]<dis[v])and(not bj[v]) then
     56                begin
     57                  dis[v]:=dis[u]+w[i];
     58                    if (not vis[v])and(not bj[v]) then
     59                       begin
     60                         vis[v]:=true;
     61                          inc(t);
     62                         q[t]:=v;
     63                       end;
     64                 end;
     65                i:=next[i];
     66            end;
     67         end;
     68        if dis[n]>b then exit(false) else exit(true);
     69   end;
     70 begin
     71  readln(n,m,b);
     72  mi:=maxlongint;
     73  for i:=1 to n do
     74   begin
     75     readln(cost[i]);
     76     if ma<cost[i] then ma:=cost[i];
     77     if mi>cost[i] then  mi:=cost[i];
     78 
     79   end;
     80   c:=cost;
     81   sort(1,n);
     82   for i:=1 to m do
     83    begin
     84     readln(x,y,z);
     85     add(x,y,z);
     86     add(y,x,z);
     87    end;
     88    l:=1; r:=n;
     89    if not check(maxlongint) then
     90   begin   writeln('AFK'); exit; end;
     91 
     92   while l<=r do
     93     begin
     94       mid:=(l+r)div 2;
     95      // blood:=b;
     96 
     97      if check(c[mid]) then
     98      begin ans:=c[mid]; r:=mid-1; end else l:=mid+1;
     99     end;
    100 
    101     writeln(ans);
    102 end.

    最优贸易noip2009

    题解:

    就因为我for 打错成n就调了一个小时!?而且这已经不是第一次了!

    ------------------------------------------------------------------------------------

    开始说正事。

    本题很直观的就是想找到一个价格最低和一个价格最高点(满足由起点能到达且又可顺序到达终点),找最低价格的点可以这样来处理, 从源点开始找到所有点的最低价格(某个顶点的最低价格就是从源点到该所有可能路径上的价格最低的点), 最后枚举卖出的点,并且判断该点是否可以到达即可。 此外,由于数据规模较大,一般的邻接矩阵难以承受, 因此采用动态数据结构邻接表。但是本题有环,处理时还有几个细节问题: 1.由于是最后要判定所有的顶点是否可以到达终点, 因此不妨将所有的边反向,由终点出发判断终点可以到达那些顶点就可以了, 并做上标记。这样也就要求在读入边的时候必须反向再储存一次。 2.用SPFA求某个顶点的最低价格时,对SPFA进行了改进。 由SPFA的原理可以知道,该算法可以处理环的问题, 但是要求最短路径的长度是可以收敛的,也就是说不能在图中存在负权。 该题目满足此要求。SPFA是用来求最短路径的算法,在此对其改进, 来求路径上最小价格的点。

     

      1 var
      2 e,ie,x,y,z,u,h,t,n,m,i,j,k,ans,v:longint;
      3 head,b,next,ihead,inext,a,ib,maxp,minp,q:array[0..500005]of longint;
      4 vis:array[0..500005]of boolean;
      5 function max(x,y:longint):longint;
      6  begin
      7   if x>y then exit(x) else exit(y);
      8  end;
      9  function min(x,y:longint):longint;
     10   begin
     11    if x>y then exit(y) else exit(x);
     12   end;
     13 procedure add(x,y:longint);
     14  begin
     15   inc(e);b[e]:=y;next[e]:=head[x];head[x]:=e;
     16  end;
     17   procedure iadd(x,y:longint);//反向建边
     18  begin
     19   inc(ie);ib[ie]:=y;inext[ie]:=ihead[x];ihead[x]:=ie;
     20  end;
     21  procedure spfa1;
     22   var i,j,h,t,u,v:longint;
     23   begin
     24    for i:=1 to n do minp[i]:=maxlongint;
     25    h:=0;t:=1; q[1]:=1;vis[1]:=true;
     26    minp[1]:=a[1];
     27    while h<t do
     28     begin
     29      inc(h);
     30      u:=q[h];
     31     vis[u]:=false;
     32      i:=head[u];
     33      while i>0 do
     34       begin
     35        v:=b[i];
     36        if minp[v]>minp[u] then
     37         begin
     38              minp[v]:=minp[u];
     39          minp[v]:=min(minp[v],a[v]);
     40          if not vis[v] then
     41           begin
     42             vis[v]:=true;
     43             inc(t);
     44             q[t]:=v;
     45           end;
     46           end;
     47            i:=next[i];
     48            end;
     49     end;
     50     
     51   end;
     52  procedure spfa2;
     53  var i,j,h,t,u,v:longint;
     54   begin
     55   fillchar(q,sizeof(q),0);
     56   fillchar(vis,sizeof(vis),false);
     57    h:=0;t:=1;
     58    q[1]:=n; vis[n]:=true;
     59    maxp[n]:=a[n];
     60    while h<t do
     61      begin
     62        inc(h);
     63        u:=q[h];
     64        i:=ihead[u];
     65       vis[u]:=false;//打在前面有负环也能运行
     66         while i>0 do
     67           begin
     68             v:=ib[i];
     69           if maxp[v]<maxp[u] then // you wrong here
     70             begin
     71               maxp[v]:=maxp[u];
     72              maxp[v]:=max(maxp[v],a[v]);
     73             if not vis[v] then
     74              begin
     75                vis[v]:=true;
     76                inc(t);
     77                q[t]:=v;
     78              end;
     79             end;
     80             i:=inext[i];
     81            
     82           end;
     83      end;
     84 
     85   end;
     86 begin
     87  readln(n,m);
     88  for i:=1 to n do
     89  read(a[i]);
     90  for i:=1 to m do//m 不要再打成n了!
     91   begin
     92    readln(x,y,z);
     93    add(x,y);
     94    iadd(y,x);
     95     if z=2 then
     96      begin
     97        add(y,x);
     98        iadd(x,y);
     99      end;
    100   end;
    101    spfa1;
    102    spfa2;
    103    for i:=1 to n do
    104      if maxp[i]-minp[i]>ans then ans:=maxp[i]-minp[i];
    105      writeln(ans);
    106 end.

     

     

     

     

     

     

    NOIP2018 rp++
  • 相关阅读:
    消息中间件——RabbitMQ(六)理解Exchange交换机核心概念!
    消息中间件——RabbitMQ(五)快速入门生产者与消费者,SpringBoot整合RabbitMQ!
    消息中间件——RabbitMQ(四)命令行与管控台的基本操作!
    消息中间件——RabbitMQ(三)理解RabbitMQ核心概念和AMQP协议!
    LayUI的基本使用
    Git报错:Your branch is up to date with 'origin/master'.
    Git报错:Please tell me who you are.
    Git报错:Permission denied (publickey)
    在 windows 上安装 git 2.22
    在 windows 上安装 git 2.15
  • 原文地址:https://www.cnblogs.com/brilliant107/p/9471267.html
Copyright © 2011-2022 走看看