zoukankan      html  css  js  c++  java
  • bzoj2407 探险 (重构图 + 最短路)

    2407: 探险

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 148  Solved: 84
    [Submit][Status][Discuss]

    Description

    探险家小T好高兴!X国要举办一次溶洞探险比赛,获奖者将得到丰厚奖品哦!小T虽然对奖品不感兴趣,但是这个大振名声的机会当然不能错过!

    比赛即将开始,工作人员说明了这次比赛的规则:每个溶洞和其他某些溶洞有暗道相连。两个溶洞之间可能有多条道路,也有可能没有,但没有一条暗道直接从自己连到自己。参赛者需要统一从一个大溶洞出发,并再次回到这个大溶洞。

    如果就这么点限制,那么问题就太简单了,可是举办方又提出了一个条件:不能经过同一条暗道两次。这个条件让大家犯难了。这该怎么办呢?

    到了大溶洞口后,小T愉悦地发现这个地方他曾经来过,他还记得有哪些暗道,以及通过每条暗道的时间。小T现在向你求助,你能帮他算出至少要多少时间才能回到大溶洞吗?

    Input

    第一行两个数n,m表示溶洞的数量以及暗道的数量。

    接下来m行,每行4个数s、t、w、v,表示一个暗道连接的两个溶洞s、t,这条暗道正着走(s -> t)的所需要的时间w,倒着走(t -> s)所需要的时间v。由于溶洞的相对位置不同,wv可能不同。

    Output

    输出一行一个数t,表示最少所需要的时间。

     

     

    (直接抄dalao的题解了orz)

    先跑一遍最短路,令$1$到$i$的最短路为$dis[i]$,并记录$1$到$i$的最短路上第一个经过的点$pre[i]$,若$pre[i]==1$则令$pre[i]=i$;

    重新构图,对于原图中的一条边$(u,v,w)$:

      若$u==1$:

        若$pre[v]==v$,忽略此边;否则连边$(S,v,w)$;

      若$v==1$:

        若$pre[u]==u$,连边$(u,T,w)$;否则连边$(S,T,dis[u]+w)$;

      若$u!=1$且$v!=1$:

        若$pre[u]==pre[v]$,连边$(u,v,w)$;否则连边$(S,v,dis[u]+w)$;

    新图中跑一边$S$到$T$最短路即可;

    这样构造把$S->i$的边拆开,就不会导致一条路走两遍;

    AC GET☆DAZE

     

    ↓代码

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<string>
      5 #include<cmath>
      6 #include<algorithm>
      7 #include<vector>
      8 #include<queue>
      9 using namespace std;
     10 struct edge
     11 {
     12     int to,next,val;
     13 }fet[400039],ret[400039];
     14 int n,fhd[40039],shd[40039],tot,rot,dis[40039],fir[40039],S,T,stp=0x3f3f3f3f;
     15 bool inq[40039],Sinogi[40039];
     16 void add(int u,int v,int ws,int wr)
     17 {
     18     fet[++tot].to=v,fet[tot].next=fhd[u],fet[tot].val=ws,fhd[u]=tot;
     19     fet[++tot].to=u,fet[tot].next=fhd[v],fet[tot].val=wr,fhd[v]=tot;
     20 }
     21 void add(int u,int v,int w)
     22 {
     23     ret[++rot].to=v,ret[rot].next=shd[u],ret[rot].val=w,shd[u]=rot;
     24 }
     25 void spfa(edge net[],int head[])
     26 {
     27     memset(dis,63,sizeof(dis));
     28     queue<int>que;
     29     que.push(S),dis[S]=0,inq[S]=1,fir[S]=S;
     30     int a,b;
     31     while(!que.empty())
     32     {
     33         a=que.front(),que.pop();
     34         for(b=head[a];b!=-1;b=net[b].next)
     35         {
     36             if(dis[net[b].to]>dis[a]+net[b].val)
     37             {
     38                 dis[net[b].to]=dis[a]+net[b].val;
     39                 fir[net[b].to]=(fir[a]==S ? net[b].to : fir[a]);
     40                 if(!inq[net[b].to])
     41                 {
     42                     que.push(net[b].to);
     43                     inq[net[b].to]=1;
     44                 }
     45             }
     46         }
     47         inq[a]=0;
     48     }
     49 }
     50 void rebuild(edge net[],int head[])
     51 {
     52     int a,b;
     53     for(a=1;a<=n;a++)
     54     {
     55         for(b=head[a];b!=-1;b=net[b].next)
     56         {
     57             if(a==S)
     58             {
     59                 if(fir[net[b].to]!=net[b].to)
     60                 {
     61                     add(1,net[b].to,net[b].val);
     62                 }
     63             }
     64             else if(net[b].to==S)
     65             {
     66                 if(fir[a]!=a)
     67                 {
     68                     add(S,T,dis[a]+net[b].val);
     69                 }
     70                 else
     71                 {
     72                     add(a,T,net[b].val);
     73                 }
     74             }
     75             else
     76             {
     77                 if(fir[a]!=fir[net[b].to])
     78                 {
     79                     add(S,net[b].to,dis[a]+net[b].val);
     80                 }
     81                 else
     82                 {
     83                     add(a,net[b].to,net[b].val);
     84                 }
     85             }
     86         }
     87     }
     88 }
     89 int main()
     90 {
     91     memset(fhd,-1,sizeof(fhd));
     92     memset(shd,-1,sizeof(shd));
     93     int m,ans=0x3f3f3f3f,a,b,c,d,e;
     94     scanf("%d%d",&n,&m);
     95     for(a=1;a<=m;a++)
     96     {
     97         scanf("%d%d%d%d",&b,&c,&d,&e);
     98         if(b==1)
     99         {
    100             Sinogi[c]=1,dis[c]=d;
    101         }
    102         if(c==1 && Sinogi[b])
    103         {
    104             stp=min(stp,d+dis[b]);
    105         }
    106         add(b,c,d,e);
    107     }
    108     S=1;
    109     spfa(fet,fhd);
    110     T=n+1;
    111     rebuild(fet,fhd);
    112     spfa(ret,shd);
    113     printf("%d",min(stp,dis[T]));
    114     return 0;
    115 }
    bzoj2407
    散りぬべき 時知りてこそ 世の中の 花も花なれ 人も人なれ
  • 相关阅读:
    java中获取服务器的IP和端口
    springboot项目 配置https
    vue+element+upload实现头像上传
    js指定日期时间加一天 ,判断指定时间是否为周末
    在内网中 vue项目添加ECharts图表插件
    vue+element树组件 实现树懒加载
    iview 表格随着更改刷新
    vue设置input不可编辑切换
    .Net程序员学用Oracle系列(3):数据库编程规范
    .Net程序员学用Oracle系列(2):准备测试环境
  • 原文地址:https://www.cnblogs.com/Sinogi/p/7458321.html
Copyright © 2011-2022 走看看