POJ3169:Layout(差分约束)

http://poj.org/problem?id=3169

题意:

一堆牛在一条直线上按编号站队,在同一位置可以有多头牛并列站在一起,但编号小的牛所占的位置不能超过编号大的牛所占的位置,这里用d[i]表示编 号为i的牛所处的位置,即要满足d[i]-d[i+1]<=0,同时每两头牛之间有以下两种关系(对于输入的a b d来说):
            1>如果是喜欢关系:即需要满足d[b]-d[a]<=d
            2>如果是讨厌关系:即需要满足d[b]-a[a]>=d ……> d[a]-d[b]<=-d
   由于题目要求队伍的最大可能长度,即求满足以下三个约束条件的最大值,,由于此处是求最大值,故用Bellman_Ford算法求约束图的最短路径.
            1>对于ML有:d[b]-d[a]<=d
            2>对于MD有:d[a]-d[b]<=-d
            3>对于n个顶点的约束图有:s[i]-s[i+1]<=0(隐含条件)
    题目的解为:有负环输出-1,d[n]无穷大输出-2,其他输出dist[n].
    在差分约束系统中如果题目要求是求最小值,就将约束条件转化为">="形式,然后用Bellman_Ford算法求解约束图的最长路径,如果题目要 求的是最大值,就将约束条件转化为"<="形式,然后用Bellman_Ford算法求解约束图的最短路径.

PS:
(1)INF不能开得太大,可能会溢出;
(2)数组尽量开小,不然会比较慢

如果有负环,输出-1,如果N可以无限远,即1与N不连通,输出-2,其他情况输出1与N的最大距离。(最短路)

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <queue>
#define N 1000001
using namespace std;
int n,m,k,tt;
int head[1001],v[1001],dis[1001];
struct node
{
    int x,y,z;
    int next;
} q[1000001];
void init()
{
    memset(head,-1,sizeof(head));
    tt=0;
}
void add(int xx,int yy,int zz)
{
    q[tt].x=xx;
    q[tt].y=yy;
    q[tt].z=zz;
    q[tt].next=head[xx];
    head[xx]=tt++;
}
void SPFA()
{
    for(int i=1; i<=n; i++)
    {
        dis[i]=N;
        v[i]=0;
    }
    dis[1]=0;
    v[1]=1;
    queue<int>p;
    p.push(1);
    while(!p.empty())
    {
        int ff=p.front();
        p.pop();
        v[ff]=0;
        for(int i=head[ff]; i!=-1; i=q[i].next)
        {
            if(dis[q[i].y]>dis[ff]+q[i].z)
            {
                dis[q[i].y]=dis[ff]+q[i].z;
                if(dis[q[i].y]<0)//不存在最短路(这题是实际问题,不会出现负边//或者根据有顶点入队列的次数大于n)
                {
                    printf("-1
");
                    return ;
                }
                if(!v[q[i].y])
                {
                    v[q[i].y]=1;
                    p.push(q[i].y);
                }
            }
        }
    }
    if(dis[n]==N) printf("-2
");//1到n没有路
    else printf("%d
",dis[n]);
    return ;
}
int main()
{
    int xx,yy,zz;
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        init();
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d%d",&xx,&yy,&zz);
            add(xx,yy,zz);
        }
        for(int i=1; i<=k; i++)
        {
            scanf("%d%d%d",&xx,&yy,&zz);
            add(yy,xx,-zz);
        }
        for(int i=1; i<n; i++)//隐含条件
        {
            add(i+1,i,0);
        }
        SPFA();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zhangmingcheng/p/3940795.html