[SHOI2012]回家的路
[SHOI2012]回家的路
题意:
给定 \(2n\) 条路径,横竖交叉形成一个网格图,走一条边时不能更换边,其中有些交叉点可以更换边,消耗 \(1\),走过一条边,消耗 \(2\).
给定起点终点,询问最小值。
分析:
可以发现,我们连接所有边其实没啥用,而且还炸空间时间。
事实上,在这个图上有用的点只有:交叉点和起点终点。
因为只有这些点能使变换方向,其他正着竖着走都无所谓。我们将这些点编号成 \([1,m]\) 号。
先不考虑换乘时间,因此只能考虑 \(x_i=x_j\) 或者 \(y_i=y_j\) 的情况。对于横或纵坐标相同的点,依次相连建立双向边,边权即为距离 \(\times 2\)。
但是,怎么处理换乘时间呢?我们总不能说:经过这个点就 \(+1\),这样肯定是不行的。
考虑分层图:我们把整个图分成两层,将 \(i\in [1,m]\),\(i\) 对 \(i+m\) 建立权值为 \(1\) 的双向边。
然后处理一下两层的边权,注意两层的起点终点也要建立双向边,权值为 \(0\).
代码:
//P3831 [SHOI2012]回家的路
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mk make_pair
using namespace std;
const int N=1e6+5;
int n,m,s,t;
int nxt[N],ver[N],edge[N],head[N],tot;
int dis[N],vis[N];
int len(int x,int y){ return 2*abs(y-x);}
void add(int x,int y,int z){
ver[++tot]=y; nxt[tot]=head[x]; head[x]=tot; edge[tot]=z;
}
struct node{
int x,y,id;
}a1[N],a2[N];
bool cmp1(node a,node b){
return a.x==b.x?a.y<b.y:a.x<b.x;
}
bool cmp2(node a,node b){
return a.y==b.y?a.x<b.x:a.y<b.y;
}
priority_queue<pii> q;
void dijkstra(int s){
memset(dis,0x3f3f3f3f,sizeof(dis));
dis[s]=0;
q.push(mk(0,s));
while(!q.empty()){
int x=q.top().second; q.pop();
if(vis[x]) continue;
vis[x]=1;
for(int i=head[x];i;i=nxt[i]){
int y=ver[i],z=edge[i];
if(dis[y]>dis[x]+z){
dis[y]=dis[x]+z; q.push(mk(-dis[y],y));
}
}
}
}
int main(){
cin>>n>>m; m+=2;
for(int i=1;i<=m;i++){
scanf("%d%d",&a1[i].x,&a1[i].y); a2[i].x=a1[i].x,a2[i].y=a1[i].y;
a1[i].id=i,a2[i].id=i+m;
if(i==m-1) s=i; if(i==m) t=i;
}
sort(a1+1,a1+1+m,cmp1);
sort(a2+1,a2+m+1,cmp2);
for(int i=1;i<m;i++){
if(a1[i].x!=a1[i+1].x) continue;
add(a1[i].id,a1[i+1].id,len(a1[i+1].y,a1[i].y));
add(a1[i+1].id,a1[i].id,len(a1[i+1].y,a1[i].y));
}
for(int i=1;i<m;i++){
if(a2[i].y!=a2[i+1].y) continue;
add(a2[i].id,a2[i+1].id,len(a2[i+1].x,a2[i].x));
add(a2[i+1].id,a2[i].id,len(a2[i+1].x,a2[i].x));
}
for(int i=1;i<=m-2;i++){
add(i,i+m,1); add(i+m,i,1);
}
add(s,s+m,0); add(s+m,s,0); add(t,t+m,0); add(t+m,t,0);
dijkstra(s);
if(dis[t]==0x3f3f3f3f) puts("-1");
printf("%d\n",dis[t]);
system("pause");
return 0;
}
不关注的有难了😠😠😠https://b23.tv/hoXKV9