• 【bzoj1726/Usaco2006 Nov】Roadblocks第二短路——SPFA


    题目链接

    分析:题目要求一个连通图的从1到n的严格次短路,我们只需要在跑最短路的时候顺便判一下次短路是否能够被更新即可。

    dis[x][0]表示1到x的最短路,而dis[x][1]则表示次短路,需要分成三类讨论:

    dis[x][0]+e[i].w<dis[to][0],此时dis[x][1]是原最短路和dis[x][1]+e[i].w的较小值(注意这里最短路要在更新完次短路后再更新);

    dis[x][0]+e[i].w>dis[to][0]&&dis[x][0]+e[i].w<dis[to][1],这条路虽然不能更新最短路,但可以更新次短路;

    dis[x][0]+e[i].w==dis[to][0],因为是严格小于,所以不能把这个值赋给次短路,应为dis[to][1]=min(dis[to][1],dis[x][1]+w[i].w)。

    另外,若这条边可以更新最短路或是次短路并且to不在队列中,再将to加入队列中。

    最最后,记得每次一个点出队后要记得把标记清为0!!!

    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 #include<algorithm>
     5 const int N=5005,inf=0x3f3f3f3f;
     6 int n,m,tot=0,first[N],q[N];
     7 struct node{
     8     int ne,to,w;
     9 }e[100000*2];
    10 int read(){
    11     int ans=0,f=1;char c=getchar();
    12     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    13     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
    14     return ans*f;
    15 }
    16 int dis[N][2];
    17 bool ok[N];
    18 void add(int u,int v,int z){
    19     tot++;e[tot].ne=first[u];first[u]=tot;e[tot].to=v;e[tot].w=z;
    20     tot++;e[tot].ne=first[v];first[v]=tot;e[tot].to=u;e[tot].w=z;
    21 }
    22 int mins(int x,int y){return x>y?y:x;}
    23 void spfa(){
    24     for(int i=1;i<=n;i++)dis[i][1]=dis[i][0]=inf;
    25     dis[1][0]=0;
    26     int h=0,t=1;q[0]=1;ok[1]=1;
    27     while(h!=t){
    28         int x=q[h++];if(h>=5000)h=0;
    29         for(int i=first[x];i;i=e[i].ne){
    30             int to=e[i].to;bool ff=0;
    31             int p1=dis[x][0]+e[i].w;
    32             if(dis[to][0]>p1){
    33                 ff=1;dis[to][1]=mins(dis[to][0],dis[x][1]+e[i].w);
    34                 dis[to][0]=p1;
    35             }
    36             else if(p1>dis[to][0]&&dis[to][1]>p1)ff=1,dis[to][1]=p1;
    37             else if(dis[to][1]>dis[x][1]+e[i].w)ff=1,dis[to][1]=dis[x][1]+e[i].w;
    38             if(!ok[to]&&ff){
    39                 ok[to]=1;q[t++]=to;if(t>=5000)t=0;
    40             }
    41         }
    42         ok[x]=0;
    43     }
    44 }
    45 int main(){
    46     n=read();m=read();
    47     for(int i=1,a,b,c;i<=m;i++){
    48         a=read();b=read();c=read();
    49         add(a,b,c);
    50     }
    51     spfa();
    52     printf("%d",dis[n][1]);
    53     return 0;
    54 }
    Usaco2006
  • 相关阅读:
    【转】Android系统中Fastboot和Recovery所扮演的角色。
    【转】Android ROM分析(1):刷机原理及方法
    【转】ANDROIDROM制作(一)——ROM结构介绍、精简和内置、一般刷机过程
    【转】使用fastboot命令刷机流程详解
    检测是否安装或者开启flash
    CentOS中/英文环境切换教程(CentOS6.8)
    id: cannot find name for user ID xxx处理办法
    linux重命名所有find查找到的文件/文件夹
    linux过滤旧文件中的空行和注释行剩余内容组成新文件
    CentOS和AIX查看系统序列号
  • 原文地址:https://www.cnblogs.com/JKAI/p/7515779.html
Copyright © 2020-2023  润新知