zoukankan      html  css  js  c++  java
  • 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();
    }
  • 相关阅读:
    iptables conntrack和state的区别
    shell中test命令方法详解
    Linux Shell 中各种括号的作用 ()、(())、[]、[[]]、{}
    mac terminal ssh连接linux乱码问题
    iptables 教程,iptables 详解,iptables 常见使用实例
    Redis实现主从复制(Master&Slave)
    TCP回射客户服务器模型(02 设置套接字选项、处理多并发)
    TCP回射客户服务器模型(01 socket bind listen accept connect)
    socket套接字(字节序、地址转换)
    TCP特点
  • 原文地址:https://www.cnblogs.com/ling-zhi/p/11620491.html
Copyright © 2011-2022 走看看