poj Layout

注意:最大值不存在的情况输出\(-1\),最大值无穷大的情况输出\(-2\)
poj上有多组测试
洛谷\(hack\)数据

怎么连边

因为这是一个,我不喜欢你,我要和你挨得远,喜欢你就挨得近的问题
\(u\)\(v\)最多可相隔\(d\)就变成了\(v-u<=d\)
可以从\(u\)连向\(v\)的一条边权为\(d\)的一条边
\(u\)\(v\)最小相隔\(d\)就变成了\(v-u>=d\),然后我们取负号就变成了
\(u-v <= -d\),即从\(v\)连向\(u\)的一条\(-d\)的边

for (int i = 1, x, y, d; i <= m1; i++) {
	x = read(), y = read(), d = read();
	add(x, y, d);
}
for (int i = 1, x, y, d; i <= m2; i++) {
	x = read(), y = read(), d = read();
	add(y, x, -d);
}

操作

因为这是一个排队,所以\(i\)\(i+1\)之间要连边

for (int i = 1; i < n; i++)
	add(i + 1, i, 0);

而且我们需要判断有无负环,所以开一个超级源点判断一下有无解.

for (int i = 1; i <= n; i++)
	add(0, i, 0);

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;
} edge[N << 1];
int dis[M], vis[M], n, m1, m2;
int point[M];
int 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(dis, 0x3f, sizeof dis);
    memset(point, 0, sizeof point);
    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;
        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]) {
                    point[to]++;
                    if (point[to] == n) return -1;
                    vis[to] = 1, q.push(to);
                }
            }
        }
    }
    if (dis[n] == 0x3f3f3f3f) return -2;
    else return dis[n];
}

int main() {
    while (scanf("%d%d%d", &n, &m1, &m2) != EOF) {
        for (int i = 1; i < n; i++)
            add(i + 1, i, 0);
        for (int i = 1; i <= n; i++)
            add(0, i, 0);
        for (int i = 1, x, y, d; i <= m1; i++) {
            x = read(), y = read(), d = read();
            add(x, y, d);
        }
        for (int i = 1, x, y, d; i <= m2; i++) {
            x = read(), y = read(), d = read();
            add(y, x, -d);
        }
        int sy = spfa(0);
        if (sy <= -1) {
            cout << sy << "\n";
            continue;
        } else cout << spfa(1);
    }
}
posted @ 2020-07-19 08:52  Kersen  阅读(613)  评论(1编辑  收藏  举报