poj3169Layout(差分约束)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/readlnh/article/details/52474167

题意

有n头牛,编号是1~n,他们按编号顺序排成一排,这些牛之间有关系好的和关系坏的,关系好的ml对牛,给出他们之间的距离的最大值,关系差的md对牛,给出他们之间距离的最小值。牛可以站在同一个位置上。在满足这些条件的情况下,求编号为1的牛和n的牛距离的最大值。

思路

假如第i头牛的位置为dist[i],那么必定有dist[i] <= dist[i + 1],然后有最大距离限制,dist[a[i]] + dl[i] <= dist[b[i]],最小距离限制dist[a[i]] + dd[i] >= dist[b[i]],这些关系都可以转化成a - b <= c的形式,我们建一条b->a的权值为c的边,形成的这个图,求最短路即是最长距离,(证明:a - b <= x1, b - c <= x2, a - c <= x3, a - c <= min(x1 + x2, x3))。

代码

#include <cstdio>
#include <iostream>
using namespace std;

const int kMaxn = 10000 + 10;
const int kInf = 0x3f3f3f3f;

struct Edge {
  int u,v;
  int w;
} g[kMaxn * 3];

int dist[kMaxn];

int n,ml,md,top;

void Init() {
  top = 0;
}

void AddEdge(int a, int b, int d) {
  top++;
  g[top].u = a;
  g[top].v = b;
  g[top].w = d;
}

void Bellman_Ford(int s, int t) {
  for(int i = 1; i <= n; i++)
    dist[i] = kInf;
  dist[s] = 0;
  for(int k = 1; k < n; k++) {
    for(int i = 1; i <= top; i++) {
      if(dist[g[i].u] != kInf && dist[g[i].u] + g[i].w < dist[g[i].v])
    dist[g[i].v] = dist[g[i].u] + g[i].w;
    }
  }
}

int main() {
  while(~scanf("%d %d %d", &n, &ml, &md)) {
    int a,b,d;
    Init();
    for(int i = 1; i <= ml; i++) {
      scanf("%d %d %d", &a, &b, &d);
      AddEdge(a, b, d);
    }
    for(int i = 1; i <= md; i++) {
      scanf("%d %d %d", &a, &b, &d);
      AddEdge(b, a, -d);
    }
    //printf("%d\n", top);
    for(int i = 1; i < n; i++)
      AddEdge(i + 1, i, 0);
    //printf("%d\n", top);
    Bellman_Ford(1, n);
    if(dist[1] < 0)
      printf("-1\n");
    else if(dist[n] == kInf)
      printf("-2\n");
    else 
      printf("%d\n", dist[n]);
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/readlnh/article/details/52474167