• [NOI2014]魔法森林题解


      这道题正解其实是LCT,然而貌似SPFA也可以成功水过,所以根本不知道LCT的我只能说SPFA了。

      这道题最大的限制是两种精灵就意味着一条道可能有两个权值,因此我们需要去将其中一个固定,然后再推另一个权值,也就是说,我们可以,枚举每一条边的a,然后只走a值不大于他的边。

      然而并没有那么容易,本题数据极大,这种算法一半分都拿不到,因此我们需要别的优化,首先,我们可以现将每个边按照a的大小进行排序,然后从小到大边枚举边加边,这时dis数组就不必去每次spfa都清空了,而且每次枚举边都可以在原来的图的基础上直接加边,且当前边一定都是能走的边,不必再算上那些不满足要求的边了,可以大大地优化是时间复杂度。

      

     1 #include<iostream>
     2 #include<cstdlib>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<map>
     7 #include<queue>
     8 #include<string>
     9 #include<cmath>
    10 using namespace std;
    11 int n,m,zz,a[500005];
    12 struct ro{
    13     int to,from;
    14     int next;
    15     int a,b;
    16 }road[2000005];
    17 struct no{
    18     int a,b,from,to;
    19 }node[200004];
    20 void build(int x,int y,int z,int zx)
    21 {
    22     zz++;
    23     road[zz].from=x;
    24     road[zz].to=y;
    25     road[zz].next=a[x];
    26     road[zz].a=z;
    27     road[zz].b=zx;
    28     a[x]=zz;
    29 }
    30 int dis[500005];
    31 queue<int> q1;
    32 bool rd[500005];
    33 int ans=0x7fffffff;
    34 void spfa(int x0,int y0,int z,int zx){
    35     rd[x0]=rd[y0]=1;
    36     q1.push(x0);
    37     q1.push(y0);
    38     while(!q1.empty())
    39     {
    40         int x=q1.front();
    41         q1.pop();
    42         rd[x]=0;
    43         for(int i=a[x];i>0;i=road[i].next)
    44         {
    45             int y=road[i].to;
    46             
    47             if(dis[y]>max(dis[x],road[i].b))
    48             {
    49                 dis[y]=max(dis[x],road[i].b);
    50                 if(!rd[y])
    51                 {
    52                     q1.push(y);
    53                     rd[y]=1;
    54                 }
    55             }
    56         }
    57     }
    58     int an=0;
    59     an=dis[n];
    60     if(an!=dis[0]&&ans>an+z)
    61         ans=an+z;
    62 }
    63 int px(no a,no b)
    64 {
    65     return a.a<b.a;
    66 }
    67 int main(){
    68     memset(dis,0x7f,sizeof(dis));
    69     scanf("%d%d",&n,&m);
    70     for(int i=1;i<=m;i++)
    71     {
    72         int x,y,z,zx;
    73         scanf("%d%d%d%d",&x,&y,&z,&zx);
    74         node[i].a=z;
    75         node[i].b=zx;
    76         node[i].to=y;
    77         node[i].from=x;
    78     }
    79     sort(node+1,node+m+1,px);
    80     dis[1]=0,rd[1]=1;
    81     q1.push(1);
    82     for(int i=1;i<=m;i++)
    83     {
    84         int bj=i;
    85         build(node[i].from,node[i].to,node[i].a,node[i].b);
    86         build(node[i].to,node[i].from,node[i].a,node[i].b);
    87         spfa(node[i].from,node[i].to,node[i].a,node[i].b);
    88     }
    89     if(ans==0x7fffffff) ans=-1;
    90     printf("%d
    ",ans);
    91 //    while(1);
    92     return 0;
    93 }
    View Code
  • 相关阅读:
    软件测试 -- alpha测试和beta测试的区别
    软件测试--各种测试的概念
    linux 安装memcached
    Visual Studio 2013 Preview
    基于HAL库STM32的FSMC驱动8位TFTLCD屏
    LM358电压跟随器
    广耦的应用
    MOS管的开关作用
    三极管的开关作用
    STM32的BOOT0 BOOT1的选择
  • 原文地址:https://www.cnblogs.com/liutianrui/p/7343818.html
Copyright © 2020-2023  润新知