虫洞路线
题目描述
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;
}