POJ 3169 Layout(差分约束 线性差分约束)

题意:

有N头牛, 有以下关系:

(1)A牛与B牛相距不能大于k

(2)A牛与B牛相距不能小于k

(3)第i+1头牛必须在第i头牛前面

给出若干对关系(1),(2)

求出第N头牛与第一头牛的最长可能距离, 若无解输出-1, 若无限长输出-2

分析:

3个关系对应的 <= 式子是:

dis[b] - dis[a] <= d(1)

dis[a] - dis[b] <= -d(2)

dis[i] - dis[i+1] <= -1(2)

目标式:dis[N] - dis[1] <= T

要求这个T就是建好图后跑源点为1的最短路, 有负权环路则无解输出-1, 不连通则输出-2(无约束关系)。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstring>
#include <cmath>
#include <iomanip>
#define rep(i,a,b) for(int i = a; i < b;i++)
#define _rep(i,a,b) for(int i = a; i <= b;i++)
using namespace std;
const int inf = 1e9 + 7;
const int maxn = 1000 + 7;
int n , m;
struct edge{
    int to , d;
    edge(int _to, int _d): to(_to), d(_d){}
};
vector<edge> G[maxn];
void add_edge(int u, int v, int d){
    G[u].push_back(edge(v,d));
}
int N , ML, MD;
int dis[maxn], enter_cnt[maxn];
int spfa(){
    fill(dis, dis+maxn, inf);
    memset(enter_cnt, 0, sizeof(enter_cnt));
    bool vis[maxn];
    memset(vis, 0, sizeof(vis));

    queue<int> q;
    vis[1] = 1;
    dis[1] = 0;
    q.push(1);
    ++enter_cnt[1];

    while(!q.empty()){
        int u = q.front();
        rep(i,0,G[u].size()){
            int v = G[u][i].to, d = G[u][i].d;
            if(dis[v] > dis[u] + d){
                dis[v] = dis[u] + d;
                if(!vis[v]){
                    if(++enter_cnt[v] >= N) return -1;//入队次数大于等于N代表存在负权环路
                    vis[v] = 1;
                    q.push(v);
                }
            }
        }
        vis[u] = 0;
        q.pop();
    }
    return dis[N]; 
}
int main(){
    cin >> N >> ML >> MD;
    rep(i,0,ML){
        int a, b, d;
        cin >> a >> b >> d; //dis[b] - dis[a] <= d
        add_edge(a,b,d);
    }
    rep(i,0,MD){
        int a, b, d;
        cin >> a >> b >> d; // dis[b] - dis[a] >= d  ->  dis[a] - dis[b] <= -d
        add_edge(b,a,-d);
    }
    rep(i,1,N){ //dis[i+1] - dis[i] >= 1 ->  dis[i] - dis[i+1] <= -1
        add_edge(i+1,i,-1);
    }
    int ans = spfa();
    if(ans == -1){
        printf("-1\n");
    }else if(ans == inf){
        printf("-2\n");
    }else printf("%d\n", ans);
    return 0;
}

 

posted @ 2018-01-25 22:57  Neord  阅读(104)  评论(0编辑  收藏  举报