• P2865 [USACO06NOV]路障Roadblocks


    题目传送门

    这题题意很明确,就是求图的次短路,我用了一个非常奇葩的方法:伟大的分类讨论;

    注意,以下说明均针对无向图

    首先,图的次短路只有2种情况:

    1)1次最短路+乱转(源点->最短路上离其他点最近的点->离它最近的点->返回这个点->终点)

    2)直接次短路(依次屏蔽每一条边)

    可以证明,无向图的次短路仅有这2种情况,如有错误,请读者在评论区指出

    2的情况非常好做,仅需依次屏蔽每一条边(最短路上的)后求最短路就好了,1号情况可以邻接表打擂台去取最小值即可

    请读者务必好好理解最短路路径记忆的方法,非常非常重要!!!

    参考程序如下:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<queue>
     5 using namespace std;
     6 int n,m,x,y,z,v[200005],w[200005],nxt[200005],head[200005],cnt,dist[200005],pre[200005],edge[200005];
     7 int minn1,lesss,ans,minn2,minn3,ans1=21374404,ans2,ans3,minn4;
     8 int path[100000],num;
     9 bool vis[200005];
    10 void add(int a,int b,int c)
    11 {
    12     v[++cnt]=b;
    13     w[cnt]=c;
    14     nxt[cnt]=head[a];
    15     head[a]=cnt;
    16 }
    17 void spfa(int s)
    18 {
    19     memset(dist,20,sizeof(dist));
    20     queue<int>q;
    21     q.push(s);
    22     dist[s]=0;
    23     vis[s]=1;
    24     while(!q.empty())
    25     {
    26         int c=q.front();
    27         q.pop();
    28         vis[c]=0;
    29         for(int i=head[c];i;i=nxt[i])
    30         {
    31             int y=v[i];
    32             if(dist[y]>dist[c]+w[i])
    33             {
    34                 pre[y]=i;edge[y]=c;
    35                 dist[y]=dist[c]+w[i];
    36                 if(!vis[y])
    37                 {
    38                     q.push(y);
    39                     vis[y]=1;
    40                 }
    41             }
    42         }
    43     }
    44 }
    45 int main()
    46 {
    47     cin>>n>>m;
    48     for(int i=1;i<=m;i++)
    49     {
    50         cin>>x>>y>>z;
    51         add(x,y,z);
    52         add(y,x,z);
    53     }
    54     spfa(1);
    55     minn3=dist[n]*3;
    56     int s=21370444;
    57     for(int i=head[n];i;i=nxt[i])
    58     {
    59         s=min(s,w[i]*2);
    60     } 
    61     minn2=dist[n]*2+s;
    62     s=21370444;
    63     for(int i=head[1];i;i=nxt[i])
    64     {
    65         s=min(s,w[i]*2);
    66     } 
    67     minn4=dist[n]*2+s;
    68     minn1=dist[n];
    69     int now=n;
    70     while(now!=1)
    71     {
    72         path[++num]=pre[now];
    73         now=edge[now];
    74     }
    75     for(int i=1;i<=num;i++)
    76     {
    77         int s=w[path[i]];
    78         w[path[i]]=99999999;
    79         spfa(1);
    80         lesss=dist[n];
    81         if(lesss!=minn1)ans1=min(ans1,lesss);
    82         w[path[i]]=s;
    83     }
    84     ans=min(ans1,min(minn2,min(minn3,minn4)));
    85     cout<<ans;
    86     return 0;
    87 }
    View Code

      

  • 相关阅读:
    R镜像源的切换
    GWAS中的名称概念
    mac显示隐藏的文件,安装cocoapods
    swift开发笔记28 SlideBarMenu
    MAC读取安卓手机的APP的log日志
    关于DES加密中的 DESede/CBC/PKCS5Padding
    swift开发笔记27 UserNotifications
    swift开发笔记26 3D Touch
    银联Pos终端签到、签退、批结算、批上送、PinKey、MacKey、KEK、主密钥、工作密钥、TPDU、报文头
    开发感悟
  • 原文地址:https://www.cnblogs.com/szmssf/p/10999723.html
Copyright © 2020-2023  润新知