码迷,mamicode.com
首页 > 其他好文 > 详细

luogu_P4822 [BJWC2012]冻结

时间:2019-10-03 22:02:16      阅读:93      评论:0      收藏:0      [点我收藏+]

标签:lin   ++i   ffffff   信息   5*   分层   txt   这不   int   

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]冻结

标签:lin   ++i   ffffff   信息   5*   分层   txt   这不   int   

原文地址:https://www.cnblogs.com/ling-zhi/p/11620491.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!