题解:P5590 赛车游戏
这个题,怎么这么牛。
思路
考虑所有 \(1 \to n\) 的长度等长的限制,这个条件等价于,每条边都可以作为最短路上的边。对于传统的差分约束,我们有 \(d_u \le d_v+w\),显然,当 \((u,v)\) 被最短路经过时,有 \(d_u=d_v+w\),因为如果 \(d_u\) 比 \(d_v +w\) 小, \(d_u\) 就会被松弛,这样就满足了所有最短路相等的限制,洛谷上很多题解这个点都是没讲清楚的。对于此题,我们有 \(w \in [1,9]\),把前面的等式移项,得到 \(d_u-d_v=w\),即 \(1 \le d_u-d_v \le 9\),跑差分约束即可。
然后需要注意,跑差分约束的时候只需要保留 \(1 \to u\) 且 \(u \to n\) 的 \(u\),其余随便赋一个值即可,具体实现可以正图反图分别跑一遍 DFS。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1005,M=2005;
struct edge{
int to,nxt;
}e[2][M*2];
int hd[2][N],tot1,tot2;
int uu[M],vv[M],ww[M];
void add(int u,int v,int op){
if(op==0){
e[0][++tot1].to=v;
e[0][tot1].nxt=hd[0][u];
hd[0][u]=tot1;
}else{
e[1][++tot2].to=v;
e[1][tot2].nxt=hd[1][u];
hd[1][u]=tot2;
}
}
int tag[2][N],op;
void dfs(int u){
tag[op][u]=1;
for (int i=hd[op][u];i;i=e[op][i].nxt){
int v=e[op][i].to;
if (tag[op][v])continue;
dfs(v);
}
}
struct edge2{
int to,nxt,w;
}Ee[M*4];
int H[N],tt,dis[N],cnt[N];
bool vis[N];
void Add(int u,int v,int w){
Ee[++tt]={v,H[u],w};
H[u]=tt;
}
bool spfa(int s,int n){
memset(dis,0x3f,sizeof dis);
memset(cnt,0,sizeof cnt);
memset(vis,0,sizeof vis);
queue<int>q;
dis[s]=0;
vis[s]=1;
q.push(s);
while(!q.empty()){
int u=q.front();q.pop();
vis[u]=0;
for(int i=H[u];i;i=Ee[i].nxt){
int y=Ee[i].to;
if(dis[y]>dis[u]+Ee[i].w){
dis[y]=dis[u]+Ee[i].w;
if(!vis[y]){
if(++cnt[y]>n)return 1;
vis[y]=1;
q.push(y);
}
}
}
}
return 0;
}
int main(){
int n,m;cin>>n>>m;
for (int i=1;i<=m;++i){
int u,v;cin>>u>>v;
uu[i]=u;vv[i]=v;
add(u,v,0);
add(v,u,1);
}
op=0; dfs(1);
op=1; dfs(n);
if(!tag[0][n]){
cout<<-1;
return 0;
}
memset(H,0,sizeof H);
tt=0;
for(int i=1;i<=m;++i){
int u=uu[i],v=vv[i];
if(tag[0][u]&&tag[1][u]&&tag[0][v]&&tag[1][v]){
Add(v,u,-1);
Add(u,v,9);
}else{
ww[i]=1;
}
}
for(int i=1;i<=n;++i){
Add(0,i,0);
}
if(spfa(0,n+1)){
cout<<-1;
return 0;
}
for(int i=1;i<=m;++i){
int u=uu[i],v=vv[i];
if(tag[0][u]&&tag[1][u]&&tag[0][v]&&tag[1][v]){
int w=dis[v]-dis[u];
if(w<1||w>9){
cout<<-1;
return 0;
}
ww[i]=w;
}else{
ww[i]=1;
}
}
cout<<n<<" "<<m<<"\n";
for(int i=1;i<=m;++i){
cout<<uu[i]<<" "<<vv[i]<<" "<<ww[i]<<"\n";
}
return 0;
}

浙公网安备 33010602011771号