POJ3169Layout(线性约束)

题目大意:有n头牛排成一列,这些牛排列时候,有这个两个条件,A、B两头牛间的距离最大为D,或者A、B两头牛之间的距离至少为D,前ML个约束是第一种约束,后MD个约束是第二种约束,求第1头牛到第N头牛可能的最远距离。如果距离可以无限大,打印出-2, 如果不存在这样的排列打印出-1。

分析:限制一转化为不等式即为d[b] - d[a] <= D,即a->b的边的权值为D。限制条件二转化为不等式即为d[b] - d[a] >= D等价于d[a] - d[b]  <= -d,即b->a的边权值为-D,求两个变量之间的最大值,就转化成了求最短路。


AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int maxn = 20005;
const int INF = 0x3f3f3f3f;
struct edge
{
    int v, w, next;
}Edge[maxn];
int head[maxn], dis[maxn], time[maxn], cnt, n, ml, md;
bool vis[maxn];
void add_edge(int u, int v, int w)
{
    Edge[cnt].v = v;
    Edge[cnt].w = w;
    Edge[cnt].next = head[u];
    head[u] = cnt++;
}
int spfa(int s, int tol)
{
    memset(dis, 63, sizeof(dis));
    memset(time, 0, sizeof(time));
    memset(vis, false, sizeof(vis));
    dis[s] = 0;
    vis[s] = true;
    time[s]++;
    queue<int> q;
    q.push(s);
    while(!q.empty())
    {
        int tem = q.front();
        q.pop();
        vis[tem] = false;       //注意取消标记一定要放在这边,因为图的题目中一个点可能自身有负环
        for(int i = head[tem]; i != -1; i = Edge[i].next)
        {
            int to = Edge[i].v;
            if(dis[to] > dis[tem] + Edge[i].w)
            {
                dis[to] = dis[tem] + Edge[i].w;
                if(!vis[to])
                {
                    vis[to] = true;
                    q.push(to);
                    time[to]++;
                    if(time[to] >= tol)     //如果入队列超过n次(点的个数), 那么就存在负环,因为一个图的最短路肯定由不大于n-1条边构成
                        return -1;
                }
            }
        }
    }
    return dis[n];
}
int main()
{
    int u, v, w;
    while(cin >> n >> ml >> md)
    {
        cnt = 0;
        fill(head, head + n + 1, -1);
        for(int i = 0; i < ml; i++)
        {
            scanf("%d%d%d", &u, &v, &w);
            add_edge(u, v, w);
        }
        for(int i = 0; i < md; i++)
        {
            scanf("%d%d%d", &u, &v, &w);
            add_edge(v, u, -w);
        }
        int ans = spfa(1, ml + md);
        if(ans == -1)
            cout << -1 << endl;
        else if(ans == INF)     //如果某相邻两头牛间的约束条件没有给出,那么这两头牛之间就可以无限大
            cout << -2 << endl;
        else
            cout << dis[n] << endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值