对于题目我们可以分两种情况。
在图中,两个红色箭头为两个人现在的位置,这是一种普遍的情况,那么既然两个箭头之间的距离为x。
我们设距离的前缀和为Si ,一下的ABCD,都应该时SA SB SC SD简写了
那么显而易见 。D-A >x C-B < X 即 D-A>=x+1 C-B<=x-1
当A==B,C==D时 C-B=X 即C-B>=X 且 C-B<=X
加上超级源点
按两种情况建边就可以了,代码中以n作为超级源点,i点的前缀和为S(i-1)
#include<iostream>
#include<string.h>
#include<algorithm>
#include<vector>
#include<stdio.h>
#include<queue>
using namespace std;
const int MAXN=5e4+5;
const int INF=0x7fffffff;
struct Point
{
int v,c;
Point(){};
Point(int a,int b){v=a,c=b;}
};
vector<Point>v[MAXN];
int dis[MAXN],cnt[MAXN];
bool vis[MAXN];
int n,m,x;
void spfa()
{
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++){
dis[i]=INF;
}
vis[n]=1;
dis[n]=0;
queue<int>q;
while(!q.empty())q.pop();
q.push(n);
bool f=1;
memset(cnt,0,sizeof(cnt));
cnt[n]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(int i=0;i<v[u].size();i++){
int vv=v[u][i].v;
if(dis[vv]>dis[u]+v[u][i].c){
dis[vv]=dis[u]+v[u][i].c;
if(!vis[vv]){
vis[vv]=1;
q.push(vv);
if(++cnt[vv]>n){f=0;break;}
}
}
}
if(f==0)break;
}
if(f==0)cout<<" IMPOSSIBLE"<<endl;
else{
for(int i=1;i<n;i++){
//cout<<dis[i]<<endl;
cout<<" "<<dis[i]-dis[i-1];
}
cout<<endl;
}
}
int main()
{
int t,cnt=0;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&x);
for(int i=0;i<=n;i++){
v[i].clear();
}
for(int i=1;i<n;i++){
v[i].push_back(Point(i-1,-1));
v[n].push_back(Point(i,0));
}
for(int i=1;i<=m;i++){
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
a--,b--,c--,d--;
if(a==b&&c==d){
v[c].push_back(Point(a,-x));
v[a].push_back(Point(c,x));
}
else{
v[d].push_back(Point(a,-(x+1)));
v[b].push_back(Point(c,(x-1)));
}
}
cout<<"Case #"<<++cnt<<":";
spfa();
}
}