POJ3169 Layout (差分约束系统)

传送门
题意:有N头牛,第i头牛一定在第i-1头和第i+1头中间(按照编号从小到大排列)给出两种约束
1. A 到 B 的距离不少于 D
2. A 到 B 的距离不超过 D
要求第N头到第一头的距离最远。若无解,输出-1,若无限远,输出-2.

用dis(i)表示从第一头牛到第i头牛的距离,所以
-对于条件1有:dis(A) + D >= dis(B) 连一条从A到B的有向边权值为D(因为最大为D……)
-对于条件2有:dis(A) + D <= dis(B),变形为dis(B) - D >= dis(A),连一条从B到A的有向边权值为-D
又因为i+1要在i的后面,所以有dis(i+1) + 0 >= dis(i),连一条从i+1到i的等于0的边

#include<queue>
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 1005;
const int MAXM = 20005;
struct node
{
    int v, w;
    node *next;
}Edge[MAXM*2], *Adj[MAXN], *Mcnt = Edge;
void Addedge(int u,int v,int w)
{
    node *t = ++Mcnt;
    t->v = v;
    t->w = w;
    t->next = Adj[u];
    Adj[u] = t;
}
int n, ml, md, dis[MAXN], cnt, vis[MAXN];
bool inq[MAXN];
bool spfa(int s)
{
    memset(dis, 0x3f, sizeof dis);
    memset(vis, 0, sizeof vis);
    memset(inq, 0, sizeof inq);
    dis[s] = 0;
    inq[s] = vis[s] = 1;
    queue<int> q;
    q.push(s);
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        inq[u] = 0;
        for(node *p = Adj[u]; p; p = p->next)
        {
            int v = p->v;
            if(dis[u] + p->w < dis[v])
            {
                dis[v] = dis[u] + p->w;
                if(!inq[v])
                {
                    q.push(v);
                    ++ vis[v];
                    inq[v] = 1;
                    if(vis[v] > 6)return 1;
                }
            }
        }
    }
    return 0;
}
int main()
{
    cin>>n>>ml>>md;
    int a, b, d;
    for(int i = 1; i <= ml; i ++)
    {
        cin>>a>>b>>d;
        Addedge(a, b, d);
    }
    for(int i = 1; i <= md; i ++)
    {
        cin>>a>>b>>d;
        Addedge(b, a, -d);
    }
    for(int i = 1; i <= n-1; i ++)
        Addedge(i + 1, i, 0);
    if(spfa(1))
        printf("-1\n");
    else if(dis[n] != 0x3f3f3f3f) printf("%d\n", dis[n]);
    else printf("-2");
    return 0;
}

你可能感兴趣的:(POJ3169 Layout (差分约束系统))