完了,做的时候已经想不起来分层图这个东西了QAQ
对于这种“多种”路径加中转站的题,还有那种有若干次“特殊能力”的题,都可以考虑用分层图来做
显然只需要记录所有的中转站+起点终点,然后拆出横竖两层,一层的点之间连值为$2$的边,每个站的两层之间连值为$1$的边,然后再跑最短路。注意数组大小,还有起点和终点的两层是连零边的
1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=100005,inf=0x3f3f3f3f; 7 struct a 8 { 9 int xx,yy,id; 10 }mem[N]; 11 struct b{int node,dist;}; 12 bool operator < (b x,b y) 13 { 14 return x.dist>y.dist; 15 } 16 priority_queue<b> hp; 17 int val[6*N],dis[2*N],vis[2*N]; 18 int p[2*N],noww[6*N],goal[6*N]; 19 int n,m,t1,t2,st,ed,cnt,tot; 20 bool cmp1(a x,a y) 21 { 22 return x.xx==y.xx?x.yy<y.yy:x.xx<y.xx; 23 } 24 bool cmp2(a x,a y) 25 { 26 return x.yy==y.yy?x.xx<y.xx:x.yy<y.yy; 27 } 28 void link(int f,int t,int v) 29 { 30 noww[++cnt]=p[f],p[f]=cnt; 31 goal[cnt]=t,val[cnt]=v; 32 } 33 void Dijkstra(int s) 34 { 35 memset(dis,0x3f,sizeof dis); 36 dis[s]=0,hp.push((b){s,0}); 37 while(!hp.empty()) 38 { 39 b tt=hp.top(); hp.pop(); int tn=tt.node; 40 if(vis[tn]) continue ; vis[tn]=true; 41 for(int i=p[tn];i;i=noww[i]) 42 if(dis[goal[i]]>dis[tn]+val[i]) 43 dis[goal[i]]=dis[tn]+val[i],hp.push((b){goal[i],dis[goal[i]]}); 44 } 45 } 46 int main () 47 { 48 scanf("%d%d",&n,&m),st=++m,ed=++m; 49 link(st,st+m,0),link(st+m,st,0); 50 link(ed,ed+m,0),link(ed+m,ed,0); 51 for(int i=1;i<=ed;i++) 52 { 53 scanf("%d%d",&mem[i].xx,&mem[i].yy); 54 mem[i].id=++tot,link(tot,tot+m,1),link(tot+m,tot,1); 55 } 56 sort(mem+1,mem+1+tot,cmp1); 57 for(int i=1;i<=st;i++) 58 if(mem[i].xx==mem[i+1].xx) 59 { 60 link(mem[i].id,mem[i+1].id,2*(mem[i+1].yy-mem[i].yy)); 61 link(mem[i+1].id,mem[i].id,2*(mem[i+1].yy-mem[i].yy)); 62 } 63 sort(mem+1,mem+1+tot,cmp2); 64 for(int i=1;i<=st;i++) 65 if(mem[i].yy==mem[i+1].yy) 66 { 67 link(mem[i].id+m,mem[i+1].id+m,2*(mem[i+1].xx-mem[i].xx)); 68 link(mem[i+1].id+m,mem[i].id+m,2*(mem[i+1].xx-mem[i].xx)); 69 } 70 Dijkstra(st),dis[ed]>=inf?printf("-1"):printf("%d",dis[ed]); 71 return 0; 72 }