https://vjudge.net/problem/HDU-6252
题目大意:
n
n
n个车站,
m
m
m个条件
A
、
B
、
C
、
D
A、B、C、D
A、B、C、D,如果
A
=
B
A=B
A=B,那么小明就在车站
A
A
A,否则小明在车站
A
、
B
A、B
A、B之间,
C
、
D
C、D
C、D同理。整个过程中小花和小明的距离始终为
X
X
X,问能否找到满足限制的车站距离。
思路:差分约束,推一下式子可以发现,当
A
=
B
&
&
C
=
D
A=B\&\&C=D
A=B&&C=D时,要满足
d
[
C
]
−
d
[
B
]
=
X
d[C]-d[B]=X
d[C]−d[B]=X,否则要满足
d
[
D
]
−
d
[
A
]
>
=
X
+
1
d[D]-d[A]>=X+1
d[D]−d[A]>=X+1,
d
[
C
]
−
d
[
B
]
<
=
X
−
1
d[C]-d[B]<=X-1
d[C]−d[B]<=X−1。因为车站肯定不会在同意个位置,所以有
d
[
i
]
−
d
[
i
−
1
]
>
=
1
d[i]-d[i-1]>=1
d[i]−d[i−1]>=1。转换一下式子后,跑一遍最长路就可以了。
t
i
p
s
:
tips:
tips:跑最短路也可以,注意把边都取反,起点和终点也要取反。
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define pr pair<int,int>
using namespace std;
typedef long long ll;
const int maxn=2005;
const int maxm=10005;
struct Edge
{
int to,nxt,dis;
}edge[maxm];
int n,m,tot;
int head[maxn],vis[maxn],dis[maxn],cnt[maxn];
inline void addedge(int u,int v,int dis)
{
edge[++tot].to=v,edge[tot].nxt=head[u],edge[tot].dis=dis,head[u]=tot;
}
bool spfa()
{
for(int i=1;i<=n;i++)
{
dis[i]=-2000000001;
cnt[i]=vis[i]=0;
}
dis[1]=0,vis[1]=cnt[1]=1;
queue<int> q;
q.push(1);
int u,v;
while(!q.empty())
{
u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i;i=edge[i].nxt)
{
v=edge[i].to;
if(dis[v]<dis[u]+edge[i].dis)
{
dis[v]=dis[u]+edge[i].dis;
if(!vis[v])
{
q.push(v),vis[v]=1;
if(++cnt[v]>=n)
return 0;
}
}
}
}
return 1;
}
int main()
{
int t,times=0;
scanf("%d",&t);
while(t--)
{
int a,b,c,d,x;
scanf("%d%d%d",&n,&m,&x);
for(int i=1;i<=n;i++)
head[i]=0;
tot=0;
for(int i=1;i<n;i++)
addedge(i,i+1,1);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
if(a==b&&c==d)
addedge(a,d,x),addedge(c,b,-x);
else
addedge(a,d,x+1),addedge(c,b,-x+1);
}
printf("Case #%d:",++times);
if(!spfa())
printf(" IMPOSSIBLE\n");
else
{
for(int i=2;i<=n;i++)
printf(" %d",dis[i]-dis[i-1]);
printf("\n");
}
}
return 0;
}