poj 3169 Layout (差分约束)

来源:互联网 发布:linux route -p 编辑:程序博客网 时间:2024/05/22 05:32

题目描述

传送门

题目大意: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<iostream>#include<cstring>#include<algorithm>#include<cstdio>#include<cmath>#include<queue>#define N 200003#define inf 1000000000using 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());}
0 0
原创粉丝点击