题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6252
题目大意:
第一个人比第二个人先走了x分钟,路上有n个车站,现在有m个询问,每次询问会得到第一个人位置和第二个人的位置,表示为
【A,B】【C,D】,意思是当前第一个人在A,B车站中间,第二个人在C,D中间,当B==A时表示第一个人恰好在A车站,第二个人同
理。现在问你车站之间可能的距离。
思路:
差分约束系统,这里有一篇讲的很好的文章,https://blog.csdn.net/my_sunshine26/article/details/72849441
这类题目的大概意思就是,给你很多很多个约束条件,比如这样的不等式约束,问你能满足情况的条件,或者是另一个式子的最大/最小值
对于差分约束,可以将不等式变形为,这样是不是与最短路的松弛操作很像?所以差分约束系统可以利用最短路建立模型并且求解。
具体如何建模可以参考上面的文章,这里用hdu6525这个题目练习一下
这个题目只需要求满足条件的时间,那么最小满足的条件肯定也是满足的,所以利用差分约束建模
首先,两个相邻的站台之间的空格肯定要小于等于1,即ai+1-ai<=1,所以ai>=ai+1+1
可以建边
其次,对于每一个询问,给出a,b,c,d四个数字,因为两个人的差距恒定为x,所以可以分情况讨论
- 如果a==b且c==d,那么两个站台的距离==x,可以用一个>=一个<=两个不等式进行约束
- 其他情况,等号无法取到,可以建边d-a>x和c-b<x
最后跑最短路模型,答案就是起点到各个点的最短距离,就是一个单源最短路
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define endl '\n'
#define sc(x) scanf("%lld",&x)
using namespace std;
const int inf=0xc0c0c0c0;
const int size=2005;
struct Edge{
int u,v,w;
Edge(int u=0,int v=0,int w=0):u(u),v(v),w(w){}
};
vector<Edge> edge;
vector<int> No[2005];
int vis[2005];
int dis[2005];
int cnt[2005];
void init(int n)
{
fill(dis,dis+n+1,inf);
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
for(int i=0;i<=n;i++) No[i].clear();
edge.clear();
}
void addedge(int u,int v,int w)
{
edge.push_back(Edge(u,v,w));
No[u].push_back(edge.size()-1);
}
bool spfa(int s,int n)
{
dis[s]=0;
queue<int> Q;
Q.push(s);
while(!Q.empty())
{
int k=Q.front();
Q.pop();
vis[k]=0;
for(int i=0;i<No[k].size();i++)
{
int id=No[k][i];
if(dis[edge[id].v]<dis[k]+edge[id].w)
{
dis[edge[id].v]=dis[k]+edge[id].w;
if(!vis[edge[id].v])
{
Q.push(edge[id].v);vis[edge[id].v]=1;
if(++cnt[edge[id].v]>n) return false;
}
}
}
}
return true;
}
int main()
{
int n,m,x;
int t;
scanf("%d",&t);
for(int kace =1;kace <= t ;kace++)
{
scanf("%d%d%d",&n,&m,&x);
int i;
init(n+1);
for(int i=1;i<=n;i++)
{
addedge(i-1,i,1);
}
for(i=0;i<m;i++)
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
int pf=0;
if(a!=b||c!=d) pf=1;
addedge(c,b,-x+pf);
addedge(a,d,x+pf);
}
printf("Case #%d:",kace);
if(spfa(0,n+1)&&dis[n]!=inf)
for(int i=2;i<=n;i++)
{
printf(" %d",dis[i]-dis[i-1]);
}
else printf(" IMPOSSIBLE");
puts("");
}
return 0;
}