HDU World Exhibition
多测不清空,然后就T了10几遍.../kk
传送门
思路
由题意可以得到这样的不等式:
\(X\)行:
\(dis[B]-dis[A] \leq C\);
\(dis[A]-dis[B] \leq 0\);
\(Y\)行:
\(dis[A]-dis[B] \leq -C\);
这是转化成最短路径的写法,当然也可以转化成求最长路径;
当存在负环的时候就是\(-1\),当\(1\)和\(n\)不连通的时候就是\(-2\);否则就是\(dis[n]\)了;
用spfa算法好快;
code
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define N 20010
#define M 1010
using namespace std;
struct node {
int next, to, dis;
void clear() {
next = to = dis = 0;
}
} edge[N << 1];
int dis[M], vis[M], n, m1, m2;
int point[M], head[N << 1], add_edge;
int read() {
int s = 0, f = 0; char ch = getchar();
while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
return f ? -s : s;
}
void add(int from, int to, int dis) {
edge[++add_edge].next = head[from];
edge[add_edge].to = to;
edge[add_edge].dis = dis;
head[from] = add_edge;
}
int spfa(int st) {
memset(vis, 0, sizeof vis);
memset(point, 0, sizeof point);
for (int i = 1; i <= n; i++) dis[i] = 1000003647;
queue<int> q;
dis[st] = 0, q.push(st);
vis[st] = 1, dis[st] = 0;
while (!q.empty()) {
int fr = q.front();
q.pop(), vis[fr] = 0;
point[fr]++;
if (point[fr] == n) return -1;
for (int i = head[fr]; i; i = edge[i].next) {
int to = edge[i].to;
if (dis[to] > dis[fr] + edge[i].dis) {
dis[to] = dis[fr] + edge[i].dis;
if (!vis[to]) vis[to] = 1, q.push(to);
}
}
}
if (dis[n] == 1000003647) return -2;
else return dis[n];
}
void init() {
for (int i = 1; i <= add_edge; i++)
edge[add_edge].clear();
add_edge = 0; memset(head, 0, sizeof head);
}
int main() {
int T = read();
while (T--) {
init();
n = read(), m1 = read(), m2 = read();
for (int i = 1, x, y, d; i <= m1; i++) {
x = read(), y = read(), d = read();
add(x, y, d);
add(y, x, 0);
}
for (int i = 1, x, y, d; i <= m2; i++) {
x = read(), y = read(), d = read();
add(y, x, -d);
}
cout << spfa(1) << "\n";
}
}