POJ 3169 Layout
博客搬新家,以后就是基本只在自己的独立博客进行更新,欢迎访问。http://zihengoi.cn
题目链接:
题目链接:POJ 3169 Layout
题目大意:
n
头牛编号为
1.有
ml
组
(u,v,w)
的约束关系,表示牛
[u]
和牛
[v]
之间的距离必须
<=w
。
2.有
md
组
(u,v,w)
的约束关系,表示牛
[u]
和牛
[v]
之间的距离必须
>=w
。
问如果这
n
头无法排成队伍,则输出
解题思路:
- 对于任意i号奶牛, 1<=i<N ,在距离上应该满足: D[i+1]−D[i]>=0 ,即 D[i+1]>=D[i] ;
- 对于每个好感的描述 (i,j,k) ,假设 i<=j ,体现到距离上的要求就是: D[j]−D[i]<=k ,即 D[j]<=D[i]+k ;
- 对于每个反感的描述 (i,j,k) ,假设 i<=j ,体现到距离上的要求就是: D[j]−D[i]>=k ,即 D[i]<=D[j]+(−k) 。
1.对于差分不等式,
a−b<=c
,建一条
b
到
a
的权值为
c
的边,该边的权值即为
a,b,
间的最大值,对于不等式
a−b>=c
,建一条
b
到
a
的权值为
2.如果检测到负环,那么无解。
3.如果
d[N]
没有更新,那么可以是任意解。
复杂度分析:
时间复杂度 :
O(n∗(ml+md))
空间复杂度 :
O(n)
AC代码:
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<cstdio>
using namespace std;
const int INF = 0x7fffffff;
const int maxn = 20010;
struct Edge {
int from, to, dist;
};
struct BellmanFord {
int n,m;
vector<Edge> edges;
vector<int > G[maxn];
bool inq[maxn];
int d[maxn];
int cnt[maxn];
void init(int n) {
this -> n = n;
for(int i = 0; i < n; i++) G[i].clear();
edges.clear();
}
void AddEdge(int from, int to, int dist) {
edges.push_back((Edge){from, to, dist});
m = edges.size();
G[from].push_back(m-1);
}
bool Bellman_Ford() {
queue<int>Q;
memset(inq, 0, sizeof(inq));
memset(cnt, 0, sizeof(cnt));
for(int i = 1; i < n; i++) d[i] = INF;
d[0] = 0;
inq[0] = true;
Q.push(0);
while(!Q.empty()){
int u = Q.front(); Q.pop();
inq[u] = false;
for(int i = 0; i < G[u].size(); i++) {
Edge& e = edges[G[u][i]];
if(d[u] < INF && d[e.to] > d[u] + e.dist){
d[e.to] = d[u] + e.dist;
if(!inq[e.to]) {
Q.push(e.to);
inq[e.to] = true;
if(++cnt[e.to] > n) return true;
}
}
}
}
return false;
}
}slove;
int main()
{
int n,ml,md;
while(scanf("%d%d%d",&n,&ml,&md) != EOF){
slove.init(n);
int from,to,dist;
for(int i = 0; i < ml; i++) {
scanf("%d%d%d",&from,&to,&dist);
slove.AddEdge(from-1,to-1,dist);
}
for(int i = 0; i < md; i++) {
scanf("%d%d%d",&from,&to,&dist);
slove.AddEdge(to-1,from-1, -dist);
}
bool ans = slove.Bellman_Ford();
if(ans) printf("-1\n");
else if(slove.d[n-1] == INF) printf("-2\n");
else printf("%d\n",slove.d[n-1]);
}
return 0;
}