POJ3169 - Layout (差分约束)

题目链接:

https://cn.vjudge.net/problem/POJ-3169


题目大意:

这里写图片描述


解题过程:

刚开始是一脸懵逼的,怎么还有这种题,完全没想法。
然后看书上说是差分约束,然后和最短路类比了下,还是没看懂,最后是去网上搜了下博客,然后又自己画了画才弄懂。

http://www.cppblog.com/menjitianya/archive/2015/11/19/212292.html


题目分析:

关于最短路,设函数 d(v) 的含义是从起点到节点 v 的最短距离,那么对于任意权值为 w 的边 e = (u, v) ,都有 d(u) + w >= d(v) 成立,公式可化为 w >= d(v) - d(u) 。最短路就是求解这组方程,变量是 d(v/x) ,求解这组方程就是意味着求出满足方程的 d(v) - d(u) 的最大值。

对于这个题目,有三个约束条件,第一个是牛按编号顺序排,第二个是某两头牛之间的距离不能大于一个值,第三个是某两头牛之间的距离必须不小于一个值。

假设这两头牛分别是 uv(v > u),约束距离是 w ,对于第一个条件, d(v) - d(u) >= 0d(v) + 0 >= d(u) ,从vu建一条权值为 0 的边。

对于第二个条件,d(u) + w >= d(v),即从 uv 建一条权值为 w 的边。

对于第三个条件,d(u) + w <= d(v)d(v) - w >= d(u),从 vu 建一条权值为 -w 的边。

然后对于上面所建立的图,求出从起点到节点的最短距离即是答案。

如果这个图无法联通,表示没有可行的方案。如果存在负环,那么这个距离是可以无限大的。

AC代码:

#include <vector>
#include <cstring>
#include <queue>
#include <cstdio>
using namespace std;

const int MAX = 11234, INF = 0x3f3f3f3f;
int frequency[MAX], dist[MAX], vis[MAX];
int N, ML, MD;
vector<pair<int, int> > edge[MAX];

int spfa() {
    memset(dist, INF, sizeof(dist));
    queue<int> q;
    q.push(1);
    dist[1] = 0;

    while (!q.empty()) {
        int u = q.front();
        q.pop();
        vis[u] = 0;

        for (int i = 0; i < edge[u].size(); i++) {
            int v = edge[u][i].first;
            int w = edge[u][i].second;

            if (dist[v] > dist[u] + w) {
                dist[v] = dist[u] + w;
                if (!vis[v]) {
                    vis[v] = 1;
                    frequency[v]++;
                    if (frequency[v] > N)
                        return -INF;
                    q.push(v);
                }
            }
        }
    }

    return dist[N];
}

int main() {
    scanf("%d %d %d", &N, &ML, &MD);

    int u, v, w;
    for (int i = 2; i <= N; i++) {
        edge[i].push_back(make_pair(i-1, 0));
    }
    for (int i = 0; i < ML; i++) {
        scanf("%d %d %d", &u, &v, &w);
        edge[u].push_back(make_pair(v, w));
    }
    for (int i = 0; i < MD; i++) {
        scanf("%d %d %d", &u, &v, &w);
        edge[v].push_back(make_pair(u, -w));
    }

    int ans = spfa();
    if (ans <= -INF) {
        printf("-1\n");
    }
    else if (ans >= INF) {
        printf("-2\n");
    }
    else {
        printf("%d\n", ans);
    }
}

转载于:https://www.cnblogs.com/ACMFish/p/7222840.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值