zoukankan      html  css  js  c++  java
  • codevs 1021 玛丽卡

    题目链接:http://codevs.cn/problem/1021/

    题解:

      哦!最小值的最大值!!二分!!!……咳咳……

      SPFA算法,邻接表(邻接矩阵应该不会炸,懒得试了……)

      先进行一遍SPFA,用pre数组记录1到n的最短路径,之后枚举这条路径上的每一条边为“堵车”的路,删除该边并进行SPFA,每次进行完与当前ans比较,取较大值

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 #define MAXN 101000
     6 #define MAXM 3010000
     7 #define INF 214748364//注意,太大了会炸……
     8 int n,m,cnt,d[MAXN],heads[MAXN],q[MAXN],head,tail,pre[MAXN],ans,x,y,z;
     9 bool viss[MAXN];
    10 struct node
    11 {
    12     int u,v;
    13     int next;
    14     int val;
    15 }edge[MAXM];
    16 void add(int x,int y,int z)
    17 {
    18     edge[++cnt].u=x;
    19     edge[cnt].v=y;
    20     edge[cnt].next=heads[x];
    21     edge[cnt].val=z;
    22     heads[x]=cnt;
    23 }
    24 void SPFA(bool _)//_值为true时进行的是第一遍SPFA,需要记录最短路径
    25 {
    26     head=1;tail=2;
    27     q[1]=1;
    28     viss[1]=true;
    29     while(head<tail)
    30     {
    31         for(int i=heads[q[head]];i!=0;i=edge[i].next)
    32         {
    33             if(d[q[head]]+edge[i].val<d[edge[i].v])
    34             {
    35                 d[edge[i].v]=d[q[head]]+edge[i].val;
    36                 if(_)pre[edge[i].v]=i;//记录最短路径,pre存储边的序号
    37                 if(!viss[edge[i].v])
    38                 {
    39                     q[tail++]=edge[i].v;
    40                     viss[edge[i].v]=true;
    41                 }
    42             }
    43         }
    44         viss[q[head]]=false;
    45         head++;
    46     }
    47 }
    48 void __()//枚举最短路径上的每一条边
    49 {
    50     if(x%2)y=x+1;
    51     else y=x-1;//相邻两条单向边记录一条双向边,x,y分别记录两条边的编号
    52     z=edge[x].val;
    53     edge[x].val=edge[y].val=INF;//设置边权为很大的值相当于删除边
    54     for(int i=1;i<=n;i++)d[i]=INF;
    55     memset(viss,false,sizeof(viss));
    56     d[1]=0;
    57     memset(q,0,sizeof(q));
    58     SPFA(0);
    59     edge[x].val=edge[y].val=z;
    60     if(d[n]!=INF)ans=max(d[n],ans);
    61     x=pre[edge[x].u];//枚举下一条边
    62     if(x==0)return;
    63     __();
    64 }
    65 int main()
    66 {
    67     scanf("%d%d",&n,&m);
    68     for(int i=2;i<=n;i++)d[i]=INF;
    69     for(int i=1;i<=m;i++)
    70     {
    71         scanf("%d%d%d",&x,&y,&z);
    72         add(x,y,z);
    73         add(y,x,z);
    74     }
    75     SPFA(1);
    76     ans=max(ans,d[n]);//其实可以删掉
    77     x=pre[n];
    78     __();
    79     printf("%d",ans);
    80     return 0;
    81 }

    PS:坑爹的codevs……,数据范围不准确,数组没开够竟然还显示TLE,把程序从递归改到循环之后才从zsc那里了解到这个问题……

    循环程序可读性差,放递归程序

      

  • 相关阅读:
    使用WLC+Portal完成认证
    WLAN PSK认证
    Bug搬运工-flexconnect AP losing Vlan mapping and fall back to default vlan
    Catalyst 9400配置StackWise Virtual
    如何在Wave2 AP上更改时区
    VMware Workstation导入ova镜像文件时报错?
    Password Recovery on Cisco Catalyst 3850
    Mobility Express初始化和升级
    C9300升级-TFTP
    查看WLC的SFP模块信息
  • 原文地址:https://www.cnblogs.com/xqmmcqs/p/5965557.html
Copyright © 2011-2022 走看看