hzwer模拟赛 虫洞

【题目描述】

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

【样例说明】

按照1->3->4的路线。

/*
把一个洞拆成黑白两个洞,然后建图
注意虫洞跨越时的颜色是相对于同一时刻而言的
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
const int maxn = 30500;
const ll inf = 987654321234LL;
inline int read(){
    char ch=getchar();
    int f=1,x=0;
    while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();};
    while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();};
    return x*f;
}
struct edge{
    int v;
    int w;
    int nxt;
}e[maxn*6];
int n,m;
int cnt,head[maxn],col[maxn],w[maxn],s[maxn];
ll dis[maxn],ans;
bool vis[maxn];
void ins(int u,int v,int w){
    cnt++;
    e[cnt].v = v;
    e[cnt].w = w;
    e[cnt].nxt = head[u];
    head[u] = cnt;
}
void spfa(int st){
    for(int i = 1;i <= n+n;i++) dis[i] = inf;
    dis[st] = 0;
    queue<int> q;
    int now,to;
    q.push(st);
    vis[st] = true;
    while(!q.empty()){
        now = q.front();
        q.pop();
        for(int i = head[now];i;i = e[i].nxt){
            to = e[i].v;
            if(dis[to] > dis[now] + e[i].w){
                dis[to] = dis[now] + e[i].w;
                if(!vis[to]){
                    vis[to] = true;
                    q.push(to);
                }
            }
        }
        vis[now] = false;
    }
    ans = min(dis[n],dis[n+n]);
    cout<<ans;
}
int main(){
    freopen("holes.in","r",stdin);
    freopen("holes.out","w",stdout);
    n = read();
    m = read();
    for(int i = 1;i <= n;i++) col[i] = read();
    for(int i = 1;i <= n;i++) w[i] = read(); 
    for(int i = 1;i <= n;i++) s[i] = read();
    int u,v,k,neww;
    for(int i = 1;i <= m;i++){
        u = read();
        v = read();
        k = read();
        if(col[u] == col[v]){
            neww = k;
            ins(u,v+n,neww);
            ins(u+n,v,neww);
        }else{
            neww = k + abs(w[u]-w[v]);
            ins(u+n,v+n,neww);
            neww = max(0,k - abs(w[u]-w[v]));
            ins(u,v,neww);
        }
    }
    for(int i = 1;i <= n;i++){
        ins(i,i+n,0);
        ins(i+n,i,s[i]);
    }
    if(col[1])spfa(1+n);
    else spfa(1);
    return 0;
}

 

posted @ 2016-09-29 15:35  ACforever  阅读(507)  评论(0编辑  收藏  举报