解题:SHOI 2012 回家的路

题面

完了,做的时候已经想不起来分层图这个东西了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 }
View Code

 

转载于:https://www.cnblogs.com/ydnhaha/p/9794974.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值