POJ 3169 Layout ---差分约束 + 最短路 + 含负边处理

本文介绍了一种结合SPFA算法与差分约束的方法来解决牛排队问题。该问题涉及寻找一组牛间的最大可能距离,同时满足特定的约束条件。通过使用SPFA算法进行最短路径计算并结合差分约束系统,文章详细解释了如何实现这一目标。

题意:n头牛编号为1到n,按照编号的顺序排成一列,每两头牛的之间的距离 >= 0。这些牛的距离存在着一些约束关系:1.有ml组(u, v, w)的约束关系,表示牛[u]和牛[v]之间的距离必须 <= w。2.有md组(u, v, w)的约束关系,表示牛[u]和牛[v]之间的距离必须 >= w。问如果这n头无法排成队伍,则输出-1,如果牛[1]和牛[n]的距离可以无限远,则输出-2,否则则输出牛[1]和牛[n]之间的最大距离。

分析:采用SPFA算法求最短路+差分约束


样例:

Sample Input

4 2 1
1 3 10
2 4 20
2 3 3

Sample Output

27
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <cstring>
#include <string>
#define INF 0x3f3f3f3f
using namespace std;
const int MAXN = 1005;
const int E = 20005;

int n,ml,md;
int dist[MAXN],cnt[MAXN],p[E],h[MAXN],nxt[E],cost[E];
bool vis[MAXN];
int e;
void add(int u,int v,int w)
{
    p[e] = v;
    cost[e] = w;
    nxt[e] = h[u];
    h[u] = e++;

}
void init()
{
    e=0;
    int u,v,w;int i;
    cin >> n>> ml >> md;
    memset(h,-1,sizeof(h));
    for(i=1;i<=n;i++)
    {
        dist[i] = INF;
    }
    for(i=1;i<=ml;i++)
    {
        cin >> u >> v >> w;
        add(u,v,w);
    }
    for(i=1;i<=md;i++)
    {
        cin >> u >> v >> w;
        add(v,u,-w);
    }

    for(int i = 2;i<=n;i++)//di <= di+1 + 0
    {
        add(i,i-1,0);
    }
}
bool relax(int u,int v,int w)
{
    if(dist[v]>dist[u]+w)
    {
        dist[v] = dist[u]+w;
        return true;
    }
    return false;

}
int SPFA(int src,int n)
{
    memset(vis,false,sizeof(vis));
    memset(cnt,0,sizeof(cnt));
    dist[src] = 0;
    queue<int> Q;
    Q.push(src);
    vis[src] = true;
    ++cnt[src];
    int i=0;
    while(!Q.empty())
    {
        int u,v;
        u = Q.front();
        Q.pop();
        vis[u] = false;
        for(i=h[u];i!=-1;i=nxt[i])
        {
            v=p[i];
            if(relax(u,v,cost[i])&&!vis[v])
            {
                Q.push(v);
                vis[v] = true;
                if(++cnt[v]>=n)
                    return -1;
            }
        }
    }
    if(dist[n] == INF)
        return -2;
    return dist[n];
}

int main()
{
    init();
   cout<< SPFA(1,n)<< endl;
        return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值