虫洞路线

题目描述

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

【时间限制、数据范围及描述】:

时间:1s 空间:256M

对于100%的数据: 1<=N<=5000,1<=M<=30000

样例说明:按照1->3->4的路线。

本题可以开2*n个点,n个表示黑洞,另外n个表示白洞。
建边时如果当前边所连接的两个洞为相同洞时,则直接建边,燃料值不变化,若两端为不同洞,则加上或减去两洞质量差。
考虑到每过1单位时间黑洞变白洞,白洞变黑洞,那么可以由i向i+n建边,并且要考虑燃料变化。

#include <bits/stdc++.h>
namespace FastIO {
    char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n';
    int p, p3 = -1;

    void read() {}

    void print() {}

    inline int getc() {
        return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
    }

    inline void flush() {
        fwrite(buf2, 1, p3 + 1, stdout), p3 = -1;
    }

    template<typename T, typename... T2>
    inline void read(T &x, T2 &... oth) {
        int f = 0;
        x = 0;
        char ch = getc();
        while (!isdigit(ch)) {
            if (ch == '-')
                f = 1;
            ch = getc();
        }
        while (isdigit(ch)) {
            x = x * 10 + ch - 48;
            ch = getc();
        }
        x = f ? -x : x;
        read(oth...);
    }

    template<typename T, typename... T2>
    inline void print(T x, T2... oth) {
        if (p3 > 1 << 20)
            flush();
        if (x < 0)
            buf2[++p3] = 45, x = -x;
        do {
            a[++p] = x % 10 + 48;
        } while (x /= 10);
        do {
            buf2[++p3] = a[p];
        } while (--p);
        buf2[++p3] = hh;
        print(oth...);
    }
} // namespace FastIO
#define read FastIO::read
#define print FastIO::print
//======================================
using namespace std;
const int maxn=3e5+10;
const int mod=31011;
const int inf=0x3f3f3f3f;
typedef long long ll;
int n,m,t,head[maxn],vis[maxn],h[maxn],w[maxn],s[maxn];
struct node {
    int w, nxt, v;
}e[maxn*4];
inline void add(int u,int v,int w) {
    t++;
    e[t].v = v;
    e[t].w = w;
    e[t].nxt = head[u];
    head[u] = t;
}
int d[maxn];
int spfa(int s,int t) {
    queue<int> q;
    if (h[s]==1) s=s+n;
    q.push(s);
    vis[s] = 1;
    memset(d, 0x3f, sizeof(d));
    d[s]=0;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        vis[u] = 1;
        for (int i = head[u]; i; i = e[i].nxt) {
            int v = e[i].v;
            if (d[v] > d[u] + e[i].w) {
                d[v] = d[u] + e[i].w;
                if (!vis[v]) {
                    q.push(v);
                }
            }
        }
    }
    return min(d[t], d[t + n]);
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("1.txt", "r", stdin);
    //freopen("2.txt", "w", stdout);
#endif
    //======================================
    read(n, m);
    for (int i = 1; i <= n; i++) {
        read(h[i]);
    }
    for (int i = 1; i <= n; i++) {
        read(w[i]);
    }
    for (int i = 1; i <= n; i++) {
        read(s[i]);
    }
    for (int i = 1, u, v, k; i <= m; i++) {
        read(u, v, k);
        if (h[u] == h[v]) {
            add(u, v + n, k);
            add(u + n, v, k);
        } else {
            int tmp = abs(w[u] - w[v]);
            add(u, v, max(k - tmp, 0));
            add(u + n, v + n, k + tmp);
        }
    }
    for (int i = 1; i <= n; i++) {
        add(i, i + n, 0);
        add(i + n, i, s[i]);
    }
    print(spfa(1,n));
    //======================================
    FastIO::flush();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Accpted/p/13199521.html