Subway Chasing HDU - 6252(差分约束)
题意:
有n个站。
有两个人A和B。(A先出发),x min后,B也出发了
有m次询问。
每次都
[ a,b ] 和 [c,d](abcd分别表示车站,且b<=a+1(d<=c+1))
找到一组满足的解。(每个车站的时间差)
思路:
差分约束。
反思:
- 连边时,(由于是不等式)注意符号!!!!!!!
一般dis[v]<=dis[u]+w;
上面就是add(u,v,w)。 - 假如是
<
时,那么要转换成<=
.方法是
边权w减少1.
- 假如是等式,那么要连双向边。
- 一般建立一个源点,其他点连接它。
AC
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define For(i,x,y) for(int i=(x); i<=(y); i++)
#define fzhead EDGE(int _to, int _v, int _next)
#define fzbody to(_to), v(_v), next(_next)
#define mst(x,a) memset(x,a,sizeof(x))
using namespace std;
const int maxm=4e6+10;
const int maxn=2e3+10;
const int inf=0x3f3f3f3f;
struct EDGE{
int to, v, next;
EDGE(){}
fzhead:fzbody{}
}e[maxm];
int cnt,n,m,x,w;
int dis[maxn],head[maxn],vis[maxn],fuhuan[maxn];
void add(int bg, int to, int val){
e[++cnt]=EDGE(to,val,head[bg]);
head[bg]=cnt;
}
bool spfa(int n){
For(i,0,n)dis[i]=inf,vis[i]=0,fuhuan[i]=0;
queue<int>q;
q.push(0);//s=0;
dis[0]=0;vis[0]=1;
while(!q.empty()){
int u=q.front();q.pop();
vis[u]=0;
for(int i=head[u]; i!=-1; i=e[i].next){
int v=e[i].to,w=e[i].v;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
// cout<<"dis[u] dis[v] "<<dis[u]<<' ';
// cout<<dis[v]<<' '<<v<<endl;
if(!vis[v]){
q.push(v);
vis[v]=1;
fuhuan[v]++;
if(fuhuan[v]>n+1)return false;//存在负环,无解。
}
}
}
}
return true;
}
int main()
{
int t,kase=0;scanf("%d", &t);
while(t--){
mst(head,-1);cnt=0;
scanf("%d%d%d", &n, &m, &x);
int a,b,c,d;
for(int i=1; i<=m; i++){
scanf("%d%d%d%d", &a, &b, &c, &d);
if(a==b&&c==d){
add(a,c,x);
add(c,a,-x);//相等加两条边。
}
else{
add(d,a,-x-1);
add(b,c,x-1);
}
}
/*
for(int i=1; i<=n; i++){
cout<<"e[i] "<<i<<" ";
for(int j=head[i]; j!=-1; j=e[j].next){
cout<<e[j].to<<' ';
}
cout<<endl;
}
*/
for(int i=1; i<=n-1; i++)add(i+1,i,-1);
for(int i=1; i<=n; i++)add(0,i,0);
printf("Case #%d: ", ++kase);
if(spfa(n)){
for(int i=2; i<=n; i++)printf("%d ",dis[i]-dis[i-1]);
puts("");
}
else printf("IMPOSSIBLE\n");
}
return 0;
}