P3831 [SHOI2012]回家的路 题解
分析
解法 1:
每两个点都连边,跑裸的最短路。
显然, 和 非常大,暴力连边会 TLE 和 MLE。
解法 2(正解):
首先,对答案产生贡献的只有换乘站,所以我们只用连两种边:
- 一个换乘站看作 个节点,连边,边权为 (站内换乘)。
- 将 相等的换乘站相连, 相等的换乘站相连。
其中,起点和终点也要加入图中。
建完图后,因为起点有两个,一个是 ,一个是 ,以这两个为源点跑最短路,再取个最小值即可。
代码
#include <bits/stdc++.h> using namespace std; inline int read(); inline void write(int); int n,m; struct poi{ int id; int x,y; }a[200005]; struct edge{ int to,nxt,w; }e[1000005<<1]; int head[200005],idx; void link(int x,int y,int w){ e[++idx]=edge{y,head[x],w}; head[x]=idx; } bool cmp1(poi a,poi b){ if(a.x!=b.x)return a.x<b.x; return a.y<b.y; } bool cmp2(poi a,poi b){ if(a.y!=b.y)return a.y<b.y; return a.x<b.x; } int ans=INT_MAX; int dis[200005]; bool vis[200005]; void dijkstra(int s){ memset(dis,0x3f3f3f3f,sizeof dis); memset(vis,0,sizeof vis); priority_queue< pair<int,int>, vector<pair<int,int> >,greater<pair<int,int> > >q; dis[s]=0;q.push(make_pair(0,s)); while (!q.empty()){ int u=q.top().second;q.pop(); if(vis[u])continue; vis[u]=true; for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(dis[v]>dis[u]+e[i].w){ dis[v]=dis[u]+e[i].w; q.push(make_pair(dis[v],v)); } } } } int main(){ n=read();m=read(); for(int i=1;i<=m;i++){ a[i].x=read();a[i].y=read();a[i].id=i; link(i,i+m+2,1); link(i+m+2,i,1); } int x1=read(),y1=read(),x2=read(),y2=read(); a[0]=poi{0,x1,y1};a[m+1]=poi{m+1,x2,y2}; sort(a,a+m+2,cmp1); for(int i=1;i<=m+1;i++){ if(a[i-1].x==a[i].x){ link(a[i-1].id,a[i].id,abs(a[i].y-a[i-1].y)*2); link(a[i].id,a[i-1].id,abs(a[i].y-a[i-1].y)*2); } } sort(a,a+m+2,cmp2); for(int i=1;i<=m+1;i++){ if(a[i-1].y==a[i].y){ link(a[i-1].id+m+2,a[i].id+m+2,abs(a[i].x-a[i-1].x)*2); link(a[i].id+m+2,a[i-1].id+m+2,abs(a[i-1].x-a[i].x)*2); } } dijkstra(0); ans=min(dis[m+1],dis[2*m+3]); dijkstra(m+2); ans=min(ans,min(dis[m+1],dis[2*m+3])); write(ans!=0x3f3f3f3f?ans:-1); return 0; } inline int read(){ register int x=0,f=0; register char ch=getchar(); while(!isdigit(ch))f^=!(ch^45),ch=getchar(); while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return f?-x:x; } inline void write(int x){ if(x<0)putchar('-'),x=-x; if(x>=10)write(x/10); putchar(x%10+'0'); }
本文作者:tmjyh09
本文链接:https://www.cnblogs.com/tmjyh09/p/15845148.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步