luogu_P4822 [BJWC2012]冻结

Posted ling-zhi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu_P4822 [BJWC2012]冻结相关的知识,希望对你有一定的参考价值。

https://www.luogu.org/problem/P4822

现在这个大陆上有 N 个城市,M 条双向的道路。城市编号为 1~N,我们在 1 号城市,需要到 N 号城市,怎样才能最快地到达呢?
这不就是最短路问题吗?我们都知道可以用 Dijkstra、Bellman-Ford、Floyd-Warshall等算法来解决。
现在,我们一共有 K 张可以使时间变慢 50%的 SpellCard,也就是说,在通过某条路径时,我们可以选择使用一张卡片,这样,我们通过这一条道路的时间 就可以减少到原先的一半。需要注意的是:

  1. 在一条道路上最多只能使用一张 SpellCard。
  2. 使用一张SpellCard 只在一条道路上起作用。
  3. 你不必使用完所有的 SpellCard。

给定以上的信息,你的任务是:求出在可以使用这不超过 K 张时间减速的 SpellCard 之情形下,从城市1 到城市N最少需要多长时间。


 

分层图,就是只能往下一层走,不能走会从前走过的层

分层图建好了就直接最短路啦

简单易懂的分层图讲解

#include<iostream> 
#include<cstdio>
#include<cstring>

#define ri register int
#define u int
#define NN 55*105
#define MM 1005*105

namespace fast 
    inline u in() 
        u x(0);
        char s=getchar();
        while(s<0||s>9) 
            s=getchar();
        
        while(s>=0&&s<=9) 
            x=(x<<1)+(x<<3)+s-0;
            s=getchar();
        
        return x;
    


using fast::in;

namespace all 
    u cnt,N,M,K,h[NN];
    struct node 
        u to,next,va;
     a[MM<<1]; 
    inline void add(const u &x,const u &y,const u &z) 
        a[++cnt].next=h[x],a[cnt].to=y,a[cnt].va=z,h[x]=cnt;
    
    
    u d[NN],vt[NN],q[1000005];
    struct node1
        u x,y,z;
    b[MM];
    
    u run(const u &x,const u &n) 
        ri l(0),r(0),k;
        for(ri i(1);i<=n;++i) d[i]=0x7fffffff;
        d[x]=0,q[++r]=x;
        while(l<r) 
            k=q[++l],vt[k]=0;
            for(ri i=h[k]; i; i=a[i].next) 
                u y=a[i].to,z=a[i].va;
                if(d[k]+z<d[y]) 
                    d[y]=d[k]+z;
                    if(!vt[y]) 
                        vt[y]=1,q[++r]=y;
                    
                
            
        
    
    
    inline void solve()
        N=in(),M=in(),K=in();
        for(ri i(1);i<=M;++i)
            u _a(in()),_b(in()),_c(in());
            b[i].x=_a,b[i].y=_b,b[i].z=_c;
        
        for(ri i(1);i<=K;++i)//建1-k层,普遍性地用循环建 
            for(ri j(1);j<=M;++j)
                u _a(b[j].x+(i-1)*N),_b(b[j].y+(i-1)*N),_c(b[j].z);
                add(_a,_b,_c),add(_b,_a,_c);//本层 
                add(_a,_b+N,_c/2),add(_b,_a+N,_c/2);//通往下一层 
            
        
        for(ri i(K+1);i<=K+1;++i)//建第k+1层,因为不想第1-k层还有下一层,所以单独来建 
            for(ri j(1);j<=M;++j)
                u _a(b[j].x+(i-1)*N),_b(b[j].y+(i-1)*N),_c(b[j].z);
                add(_a,_b,_c),add(_b,_a,_c);//只有本层 
            
        
        run(1,N*(K+1));//共k+1层, N*(K+1)个点 
        u ans(0x7fffffff);
        for(ri i(1);i<=K+1;++i)
            ans=std::min(d[N+(i-1)*N],ans);//所有层的第N点都是可以的 
        
        printf("%d",ans);
    


int main() 
    //freopen("x.txt","r",stdin);
    all::solve();

 

以上是关于luogu_P4822 [BJWC2012]冻结的主要内容,如果未能解决你的问题,请参考以下文章

BJWC2012冻结

严格次小生成树[BJWC2010]

[BJWC2018]Border 的四种求法

[題解](水/數學)luogu_P1147連續自然數和

luogu_P2824 [HEOI2016/TJOI2016]排序

Luogu_P1516题解青蛙的约会 exgcd