虫洞

题目描述

N个虫洞,M条单向跃迁路径。从一个虫洞沿跃迁路径到另一个虫洞需要消耗一定量的燃料和1单位时间。虫洞有白洞和黑洞之分。设一条跃迁路径两端的虫洞质量差为delta。

1.从白洞跃迁到黑洞,消耗的燃料值减少delta,若该条路径消耗的燃料值变为负数的话,取为0。

2.从黑洞跃迁到白洞,消耗的燃料值增加delta。

3.路径两端均为黑洞或白洞,消耗的燃料值不变化。

作为压轴题,自然不会是如此简单的最短路问题,所以每过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。

输出格式:

一个整数,表示最少的燃料消耗。

输入输出样例

输入样例

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

其中20%的数据为1<=N<=3000的链

1<=u,v<=N, 1<=k,w[i],s[i]<=200

拆点。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <cmath>
using namespace std;
int n, m, thea[5005], tcnt, hea[10005], cnt, sx[5005], w[5005], s[5005];
int uu, vv, ww, dis[10005];
bool inq[10005];
queue<int> d;
struct Te{
    int too, nxt, val;
}te[30005];
struct Edge{
    int too, nxt, val;
}edge[120005];
void add_tedge(int fro, int too, int val){
    te[++tcnt].nxt = thea[fro];
    te[tcnt].too = too;
    te[tcnt].val = val;
    thea[fro] = tcnt;
}
void add_edge(int fro, int too, int val){
    edge[++cnt].nxt = hea[fro];
    edge[cnt].too = too;
    edge[cnt].val = val;
    hea[fro] = cnt;
}
void bui(int u){
    add_edge(u, u+n, s[u]);
    add_edge(u+n, u, 0);
    for(int i=thea[u]; i; i=te[i].nxt){
        int t=te[i].too;
        int delta=abs(w[t]-w[u]);
        if(sx[u]!=sx[t]){
            add_edge(u, t, te[i].val+delta);
            add_edge(u+n, t+n, max(0, te[i].val-delta));
        }
        else{
            add_edge(u, t+n, te[i].val);
            add_edge(u+n, t, te[i].val);
        }
    }
}
void spfa(){
    memset(dis, 0x3f, sizeof(dis));
    if(sx[1]){
        dis[1] = 0;
        d.push(1);
        inq[1] = true;
    }
    else{
        dis[1+n] = 0;
        d.push(1+n);
        inq[1+n] = true;
    }
    while(!d.empty()){
        int x=d.front();
        d.pop();
        inq[x] = false;
        for(int i=hea[x]; i; i=edge[i].nxt){
            int t=edge[i].too;
            if(dis[t]>dis[x]+edge[i].val){
                dis[t] = dis[x] + edge[i].val;
                if(!inq[t]){
                    inq[t] = true;
                    d.push(t);
                }
            }
        }
    }
}
int main(){
    cin>>n>>m;
    for(int i=1; i<=n; i++)
        scanf("%d", &sx[i]);
    for(int i=1; i<=n; i++)
        scanf("%d", &w[i]);
    for(int i=1; i<=n; i++)
        scanf("%d", &s[i]);
    for(int i=1; i<=m; i++){
        scanf("%d %d %d", &uu, &vv, &ww);
        add_tedge(uu, vv, ww);
    }
    for(int i=1; i<=n; i++)
        bui(i);
    spfa();
    printf("%d", min(dis[n], dis[n+n]));
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
bugstack栈是一个以技术为核心的社群和知识分享平台。在这个平台上,程序员、软件开发者和技术爱好者可以交流、学习和分享各种与技术相关的话题和经验。 首先,bugstack栈提供了丰富多样的技术资源。在这个平台上,用户可以找到各种编程语言、开发框架和技术工具的教程、文档和案例。这些资源涵盖了从初级到高级的各个层次,无论你是刚入门的新手还是资深的专家,都可以在这里找到适合自己的学习材料。 其次,bugstack栈注重用户之间的交流和互动。用户可以在平台上发表自己的观点、经验和问题,与其他人进行讨论和互动。这种交流不仅可以加深自己对技术的理解和掌握,还可以结交到更多志同道合的朋友和同行,激发创新思维和解决问题的能力。 此外,bugstack栈还举办各种线上线下的技术活动。比如技术讲座、技术沙龙、技术峰会等。这些活动不仅给用户提供了进一步学习和分享的机会,还可以拓宽用户的视野,了解更多前沿的技术和行业趋势。 总之,bugstack栈是一个面向技术爱好者的社群平台,它提供了丰富多样的技术资源,注重用户之间的交流和互动,举办各种技术活动,为用户提供一个学习、交流和成长的平台。无论你是想学习新技术、解决问题,还是寻找合作伙伴或者拓展人脉,这个平台都是一个理想的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值