poj 3169 Layout (差分约束)

题目描述

传送门

题目大意: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]之间的最大距离。

题解

先贴一个不错的关于差分约束的讲解
将所有的限制都转换成 yx<=z 的形式,然后x->y权值为z,然后跑最短路即可。
注意判负环和判断1,n的连通性。

代码

#include
#include
#include
#include
#include
#include
#define N 200003
#define inf 1000000000
using namespace std;
int tot,n,m1,m2,point[N],nxt[N],v[N],dis[N],c[N],can[N],cnt[N];
void add(int x,int y,int z)
{
    tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;
}
int spfa()
{
    for (int i=1;i<=n;i++) dis[i]=inf;
    for (int i=1;i<=n;i++) can[i]=0,cnt[i]=0;
    can[1]=1;  dis[1]=0; cnt[1]=1;
    queue<int> p; p.push(1);
    while (!p.empty()){
        int now=p.front(); p.pop();
        for (int i=point[now];i;i=nxt[i])
         if (dis[v[i]]>dis[now]+c[i]) {
            dis[v[i]]=dis[now]+c[i];
            if (!can[v[i]]) {
                can[v[i]]=1;
                cnt[v[i]]++;
                if (cnt[v[i]]>n) return -1;
                p.push(v[i]);
             }
         }
        can[now]=0;
    } 
    if (dis[n]==inf) return -2;
    return dis[n];
}
int main()
{
    freopen("a.in","r",stdin);
    scanf("%d%d%d",&n,&m1,&m2);
    for (int i=1;i<=m1;i++) {
        int x,y,z; scanf("%d%d%d",&x,&y,&z);
        if (x>y) swap(x,y);
        add(x,y,z);
    }
    for (int i=1;i<=m2;i++) {
        int x,y,z; scanf("%d%d%d",&x,&y,&z);
        if (x>y) swap(x,y);
        add(y,x,-z);
    }
    printf("%d\n",spfa());
}

你可能感兴趣的:(线性规划)