• 解题: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
  • 相关阅读:
    无线路由器的工作模式
    php 利用root 权限执行shell脚本
    shell 终端常用插件
    linux space/mark设置
    推送唯一标识符
    微信支付跨平台软件架构
    celery 动态配置定时任务
    两个报文是如何进行 TCP 分组传输
    接口 Interfaces
    How does Circus stack compare to a classical stack?
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/9794974.html
Copyright © 2020-2023  润新知