HDU - 3592(差分约束)
题意:
n个人编号分别是1…n在排队,排队顺序与序号相同。现在有x个喜欢关系和y个厌恶关系
对于每一个喜欢关系 :a b c 代表编号a和编号c之间的距离需要<=c
对于每一个厌恶关系:a b c 代表编号a和编号c之间的距离需要>=c
问在能否满足条件,如果满足条件求1~n之间的最大距离,如果距离无限大输出-2
分析:
假设 d[i]为编号为 i的成员距离队首的距离。
那么根据题意我们有下列约束条件
- 喜欢关系a b c需要 d[b]−d[a]<=c
- 厌恶关系a b c需要 d[b]−d[a]>=c
- 相邻之间距离大于1, d[i]−d[i−1]>=1
- 队首距离为0, d[1]=1
因为求最大,我们我们最短路求满足差分约束下的源点1到n的最小距离即可
#include<bits/stdc++.h>
#define mset(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int inf=0x3f3f3f3f;
struct Edge{
int to,w;
Edge(){}
Edge(int to,int w):to(to),w(w){}
};
int dis[1005],in[1005];//距离
vector<Edge> adja[1005];//邻接表
bool book[1005];//标记是否够在队列
bool spfa(int s,int n)//源点为s,共有n个点,求最短路
{//有负环返回true,无负环返回false
queue<int> qe;
mset(dis,inf);
mset(in,0);mset(book,0);
dis[s]=0;
qe.push(s);book[s]=true;
while(!qe.empty())
{
int u=qe.front();qe.pop();
in[u]++;book[u]=false;
if(in[u]>n) return true;
for(Edge &e:adja[u])
{
int v=e.to,w=e.w;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
if(!book[v]){
book[v]=true;
qe.push(v);
}
}
}
}
return false;
}
int T[1005];
int main()
{
ios::sync_with_stdio(false);cin.tie(0);
int t;
cin>>t;
while(t--)
{
int n,x,y;
cin>>n>>x>>y;
for(int i=0;i<=n;++i) adja[i].clear();
for(int i=0;i<x;++i)
{
int a,b,c;
cin>>a>>b>>c;
adja[a].push_back(Edge(b,c));
}
for(int i=0;i<y;++i)
{
int a,b,c;
cin>>a>>b>>c;
adja[b].push_back(Edge(a,-c));
}
for(int i=2;i<=n;++i) adja[i].push_back(Edge(1,0));
for(int i=2;i<=n;++i) adja[i].push_back(Edge(i-1,-1));
if(!spfa(1,n))
{
cout<<"-1"<<endl;
}
else{
if(dis[n]==inf)
cout<<"-2"<<endl;
else
cout<<dis[n]<<endl;
}
}
return 0;
}