• bzoj3669【NOI2014】魔法森林


    题面
    一道最短路好题……
    开始和喻队长讨论了一下,喻队长一眼切:枚举ai的上界MAX,每次把ai小于等于MAX的边加到图里,以bi为边权跑最短路。
    但是,这样做是Oai*m)的,妥妥TLE,于是我们想了一些鬼畜剪枝优化常数,然并卵……喻队长身先士卒(比喻队长带头,走在蒟蒻前面),交了一波,TLE60分。
    后来,看了题解才发现这道题是SPFA的玄学用途——维护动态加边的图的最短路!只此一家,绝无仅有!走过路过千万不要错过!于是我们就可以不用打LCT来维护一棵最小生成树(正解)
    具体做法其实很简单,每次距离数组不清零,只把新加入的边的两端点入队。这样的复杂度就是Om)的了(也许吧,毕竟SPFA太玄学了),因为最后加起来相当于对原图跑一遍SPFA
    %%%%%%%%%%%%%%%喻队长
     1     #include <algorithm>
     2     #include <iostream>
     3     #include <cstdlib>
     4     #include <cstring>
     5     #include <cstdio>
     6     #include <cmath>
     7     using namespace std;
     8     const int N=50005,M=100005,INF=50005;
     9     int gi(){
    10         int str=0;char ch=getchar();
    11         while(ch>'9' || ch<'0')ch=getchar();
    12         while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar();
    13         return str;
    14     }
    15     int n,m;
    16     struct node{
    17         int x,y,dis,dist;
    18         bool operator <(const node &pp)const{
    19             return dis<pp.dis;
    20         }
    21     }e[M];
    22     int head[N],num=0;
    23     struct Lin{
    24         int next,to,dis;
    25     }a[M<<1];
    26     void init(int x,int y,int z){
    27         a[++num].next=head[x];
    28         a[num].to=y;a[num].dis=z;
    29         head[x]=num;
    30     }
    31     void addedge(int x,int y,int z){
    32         init(x,y,z);init(y,x,z);
    33     }
    34     int t=0,sum=0,q[N*10],mod=N*10,f[N],ans=(INF<<1);bool vis[N],usd[M];
    35     bool spfa(int lim){
    36         int x,u,tmp;
    37         while(t!=sum){
    38             t++;if(t==mod)t-=mod;x=q[t];
    39             for(int i=head[x];i;i=a[i].next){
    40                 u=a[i].to;tmp=a[i].dis>f[x]?a[i].dis:f[x];
    41                 if(tmp<f[u]){
    42                     f[u]=tmp;
    43                     if(!vis[u]){
    44                         vis[u]=true;
    45                         sum++;if(sum==mod)sum-=mod;q[sum]=u;
    46                     }
    47                 }
    48             }
    49             vis[x]=false;
    50         }
    51         if(f[n]==INF)return false;
    52         ans=min(ans,f[n]+lim);
    53         return true;
    54     }
    55     void build(int sta){
    56         t=0;sum=0;
    57         for(int i=sta;i<=m && e[i].dis==e[sta].dis;i++){
    58             addedge(e[i].x,e[i].y,e[i].dist);
    59             q[++sum]=e[i].x;q[++sum]=e[i].y;
    60             vis[e[i].x]=true;vis[e[i].y]=true;
    61             usd[i]=true;
    62         }
    63     }
    64     void work(){
    65         n=gi();m=gi();
    66         for(int i=1;i<=m;i++)
    67             e[i].x=gi(),e[i].y=gi(),e[i].dis=gi(),e[i].dist=gi();
    68         sort(e+1,e+m+1);
    69         int limiter=e[m].dis;
    70         memset(f,127/3,sizeof(f));
    71         f[1]=0;
    72         for(int i=1;i<=m;i++){
    73             if(usd[i])continue;
    74             build(i);
    75             spfa(e[i].dis);
    76         }
    77         if(ans==(INF<<1))printf("-1
    ");
    78         else printf("%d
    ",ans);
    79     }
    80     int main()
    81     {
    82         work();
    83         return 0;
    84     }
    喻队长的小常数代码,比某蒟蒻快一倍
  • 相关阅读:
    Double 四舍五入保留小数
    QQ在线人数统计图数据解析
    Errors running builder 'Android Resource Manager' on project 'DeskClock'.
    批处理脚本学习笔记——程序猿版
    BZOJ 1002: [FJOI2007]轮状病毒
    《逆袭大学——传给IT学子的正能量》文件夹
    webservice 开发规范
    webservice面试题
    jdbc连接oracle数据库问题
    jdbc连接 orale 和 mysql 所需要的jar包
  • 原文地址:https://www.cnblogs.com/y142857/p/7214678.html
Copyright © 2020-2023  润新知