• 虫洞路线


    题目描述

    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 = '
    ';
        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;
    }
    
  • 相关阅读:
    分享几个Android很强势的的开源框架
    终于,我还是下决心学Java后台了
    金9银10,分享几个重要的Android面试题
    Android组件化demo实现以及遇坑分享
    谷歌被爆秘密研发新系统 欲5年内取代Android
    高级面试题总结—线程池还能这么玩?
    安卓易学,爬坑不易—腾讯老司机的RecyclerView局部刷新爬坑之路
    国庆第三天2014年10月3日10:21:39,Nutz,WebCollector,jsoup
    《程序员的思维修炼》摘抄start:2014年9月27日19:27:07
    09.27日记(2014年9月27日10:33:50),那些网站
  • 原文地址:https://www.cnblogs.com/Accpted/p/13199521.html
Copyright © 2020-2023  润新知