Layout POJ

题目链接:https://vjudge.net/problem/POJ-3169

题意:有一些奶牛,有些奶牛相互喜欢,他们之间的距离必须小于等于一个K。

有些奶牛相互讨厌,他们之间的距离必须大于等于一个K。问1号奶牛个n号奶牛最远能相距多少距离,

如果无法正常排队,输出 “ -1 ”,如果距离可以无限输出 “ -2 ”。

思路:第一次做差分约束问题,看过一些人的解释,这里写出自己的理解。

题目问的是”1号奶牛个n号奶牛最远能相距多少距离“,如果两个奶牛相互喜欢,那么为了满足题意,

我们可以把他们之间的距离变成他们之间能接受的最大距离,注意,这里有一种情况:

①|x - y| <= k1

②|y - z| <= k2

①②得出,③|x - z| <= k1 + k2

④|x - z| <= k3

为了满足三头奶牛的要求,我们需要得出一个满足①②④的一个相互距离,那么我们需要选min(k1 + k2 , k3)。

这样才能满足三头奶牛的要求。

如果相互讨厌:

①|x - y| >= k1 --> |y - x| <= -k1

②|y - z| >= k2 -->|z - y| <= -k2

①②得出,③|x - z| <= k1 + k2 --> |z - x| <= -(k1 + k2)

④|x - z| <= k3 --> |z - x| <= -k3

这里的负距离表示的是他们之间的距离加上这个负距离如果还是大于等于零的距离的话说明他们直接正常排队。

两个例子:①x和y最远相距1,y和z最远相距1,x和z最近相距3,

     ②x和y最远相距5,y和z最远相距4,x和z最近相距3

可以自己画一下图

那么我们可以表示为 出发点u,目的点v,权值w。

喜欢(u,v,w),不喜欢(v,u,-w)。

如果无法正常排队,说明图中存在负环。可以用两个例子来尝试负环情况,

加上这里的负距离表示的是他们之间的距离加上这个负距离如果还是大于等于零的距离的话说明他们直接正常排队


  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <queue>
  6 #include <map>
  7 #include <cmath>
  8 #include <iomanip>
  9 using namespace std;
 10 
 11 typedef long long LL;
 12 #define inf (1LL << 25)
 13 #define rep(i,j,k) for(int i = (j); i <= (k); i++)
 14 #define rep__(i,j,k) for(int i = (j); i < (k); i++)
 15 #define per(i,j,k) for(int i = (j); i >= (k); i--)
 16 #define per__(i,j,k) for(int i = (j); i > (k); i--)
 17 
 18 const int N = 1010;
 19 int n,ml,md;
 20 int head[N];
 21 int tot[N];
 22 int dis[N];
 23 bool used[N];
 24 int cnt;//链式前项星
 25 
 26 struct Edge{
 27     
 28     int to;
 29     int w;
 30     int next;
 31 }e[20010];
 32 
 33 void add(int u,int v,int w){
 34 
 35     e[cnt].to = v;
 36     e[cnt].w = w;
 37     e[cnt].next = head[u];
 38     head[u] = cnt++;
 39 }
 40 
 41 void spfa(){
 42 
 43     rep(i,1,n) dis[i] = inf;
 44     dis[1] = 0;
 45     queue<int> que;
 46     que.push(1);
 47     used[1] = true;
 48 
 49     bool ok = true;
 50     while(!que.empty()){
 51         int u = que.front();
 52         que.pop();
 53         used[u] = false;
 54         if(++tot[u] == n){ //判负环
 55             ok = false;
 56             break;
 57         }
 58 
 59         for(int o = head[u]; ~o; o = e[o].next){
 60             int v = e[o].to;
 61             int w = e[o].w;
 62             
 63             if(dis[v] > dis[u] + w){
 64                 dis[v] = dis[u] + w;
 65                 if(!used[v]) que.push(v);
 66             }
 67                 
 68         }
 69     }
 70 
 71     if(!ok) cout << -1 << endl;
 72     else if(dis[n] == inf) cout << -2 << endl;
 73     else cout << dis[n] << endl;
 74 }
 75 
 76 int main(){
 77 
 78     ios::sync_with_stdio(false);
 79     cin.tie(0);
 80 
 81     cin >> n >> ml >> md;
 82 
 83     rep(i,1,n) head[i] = -1;
 84 
 85     int u,v,w;
 86     rep(i,1,ml){
 87         cin >> u >> v >> w;
 88         add(u,v,w);
 89     }
 90     rep(i,1,md){
 91         cin >> u >> v >> w;
 92         add(v,u,-w);
 93     }
 94 
 95     spfa();
 96 
 97 
 98     getchar();getchar();
 99 
100     return 0;
101 }

原文地址:https://www.cnblogs.com/SSummerZzz/p/11322452.html