XYLX 10.26 虫洞/Codevs P1391 伊吹萃香

XYLX 10.26 虫洞/Codevs P1391 伊吹萃香


题目描述 N个虫洞,M条单向跃迁路径。

从一个虫洞沿跃迁路径到另一个虫洞需要消耗一定量的燃料和1单位时间。
虫洞有白洞和黑洞之分。
设一条跃迁路径两端的虫洞质量差为delta。
从白洞跃迁到黑洞,消耗的燃料值减少delta。
若该条路径消耗的燃料值变为负数的话,取为0。
从黑洞跃迁到白洞,消耗的燃料值增加delta。
路径两端均为黑洞或白洞,消耗的燃料值不变化。
作为压轴题,自然不会是如此简单的最短路问题,所以每过1单位时间黑洞变为白洞,白洞变为黑洞。
在飞行过程中,可以选择在一个虫洞停留1个单位时间,如果当前为白洞,则不消耗燃料,否则消耗s[i]的燃料。
现在请你求出从虫洞1到N最少的燃料消耗,保证一定存在1到N的路线。


输入输出


输入格式

第1行:2个正整数N,M
第2行:N个整数,第i个为0表示虫洞i开始时为白洞,1表示黑洞。
第3行:N个整数,第i个数表示虫洞i的质量w[i]。
第4行:N个整数,第i个数表示在虫洞i停留消耗的燃料s[i]。
第5..M+4行:每行3个整数,u,v,k
表示在没有影响的情况下,从虫洞u到虫洞v需要消耗燃料k。

输出格式 一个整数,表示最少的燃料消耗


样例 Sample


输入样例 4 5

1 0 1 0
10 10 100 10
5 20 15 10
1 2 30
2 3 40
1 3 20
1 4 200
3 4 200


输出样例 130


数据范围

对于30%的数据: 1<=N<=100,1<=M<=500
对于60%的数据: 1<=N<=1000,1<=M<=5000
对于100%的数据: 1<=N<=5000,1<=M<=30000, 1<=u,v<=N, 1<=k,w[i],s[i]<=200
其中20%的数据为1<=N<=3000的链
样例解释 1->3->4


分析

直接将初始状态和改变后的状态想象成两个平面,那么就可以拆点,将一个点的两种状态拆开然后全图跑最短路即可。最后在两种状态中取较小值。


代码如下

program line;
type point=^rec;
     rec=record
      e,v:longint;
      s:point;
     end;
var n,m,i,j,s,e,v:longint;
    vertex:array[1..10000] of point;
    mess,stay:array[1..5000] of longint;
    state:array[1..5000] of integer;
    queue:array[1..100000] of longint;
    visited:array[1..10000] of boolean;
    dist:array[1..10000] of longint;
    head,rear:longint;
procedure insert(s,e,v:longint);
var p:point;
begin
 new(p);
 p^.e:=e;
 if v<0 then v:=0;
 p^.v:=v;
 p^.s:=vertex[s];
 vertex[s]:=p;
end;

procedure spfa(st:longint);
var i,j,h:longint;
    p:point;
begin
 for i:=1 to 2*n do
  begin
   dist[i]:=maxlongint;
   visited[i]:=false;
  end;
 head:=1;
 rear:=1;
 queue[head]:=st;
 dist[st]:=0;
 visited[st]:=true;
 while head<>rear+1 do
  begin
   p:=vertex[queue[head]];
   h:=head;
   visited[queue[head]]:=false;
   head:=(head mod 100000) +1;
   while p<>nil do
    begin
     if dist[p^.e]>dist[queue[h]]+p^.v
      then
       begin
        dist[p^.e]:=dist[queue[h]]+p^.v;
        if not visited[p^.e]
         then
          begin
           rear:=(rear mod 100000) +1;
           queue[rear]:=p^.e;
           visited[p^.e]:=true;
          end;
       end;
     p:=p^.s;
    end;
  end;
end;

begin
 readln(n,m);
 for i:=1 to n do
  read(state[i]);
 for i:=1 to n do
  read(mess[i]);
 for i:=1 to n do
  read(stay[i]);
 for i:=1 to m do
  begin
   readln(s,e,v);
   insert(s,n+e,v+(state[s]-state[e])*abs(mess[s]-mess[e]));
   insert(n+s,e,v+((state[s] xor 1)-(state[e] xor 1))*abs(mess[s]-mess[e]));
  end;
 for i:=1 to n do
  begin
   insert(i,n+i,(state[i] and 1)*stay[i]);
   insert(n+i,i,((state[i] xor 1) and 1)*stay[i]);
  end;
 spfa(1);
 if dist[n]>dist[n+n] then write(dist[n+n])
                      else write(dist[n]);
end.

测试结果

测试点#suika1.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms
测试点#suika10.in 结果:AC 内存使用量: 2544kB 时间使用量: 28ms
测试点#suika2.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#suika3.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms
测试点#suika4.in 结果:AC 内存使用量: 624kB 时间使用量: 4ms
测试点#suika5.in 结果:AC 内存使用量: 492kB 时间使用量: 0ms
测试点#suika6.in 结果:AC 内存使用量: 492kB 时间使用量: 0ms
测试点#suika7.in 结果:AC 内存使用量: 1136kB 时间使用量: 36ms
测试点#suika8.in 结果:AC 内存使用量: 1136kB 时间使用量: 34ms
测试点#suika9.in 结果:AC 内存使用量: 2672kB 时间使用量: 35ms


#

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值