• [JLOI2011]飞行路线


    【题面】:
    飞行路线

    【思路】:
    初看此题是不是有点懵逼.jpg啊。。(反正我就是
    首先最短路(spfa)的做法还是比较明显,但是本题要求他还可以免费搭乘(k)次航线,然而(k)很小((kleq10)),可以当作(dp)的一维来处理。那么就可以考虑(dp)

    我们用(dis[i][j])表示从起点到(i)的最小花费,那么易得(dis[i][0])就是最短路的花费,其余的情况通过枚举(k)来得到。

    • (dp[v][0] = min(dp[v][0] , dp[u][0] + dis[u,v]))
    • (dp[v][k] = min(dp[v][k] , dp[u][k]+dis[u,v] , dp[u][k-1]))

    我觉得还是好理解就不给注释了。。

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define inf 0x3f3f3f3f
    using namespace std;
    
    int n,m,k;int s,t;
    
    const int MAXN = 10005;
    const int MAXM = 50005;
    
    struct edge{
        int u,v,w,nxt;
    }e[MAXM<<1];int head[MAXN];int cnt=0;bool r[MAXN];
    int dis[MAXN][15];//表示从s到i这个点使用j次技能的最短路 
    
    //dp[v][j] = max(dp[u][j]+dis(u,v) , dp[u][j-1])
    
    inline void add(int u,int v,int w){
        e[++cnt].u = u;e[cnt].v = v;e[cnt].w = w;e[cnt].nxt = head[u];head[u] = cnt;
    }
    
    queue<int>q;
    inline void spfa(){
        q.push(s);memset(dis,inf,sizeof dis);
        for(int i=0;i<=k;++i) dis[s][i] = 0;
        while(!q.empty()){
            int u = q.front();q.pop();r[u] = 0;
            for(int i=head[u];~i;i=e[i].nxt){
                int v = e[i].v;
                if(dis[u][0] + e[i].w < dis[v][0]){
                    dis[v][0] = dis[u][0] + e[i].w;
                    if(!r[v]){
                        r[v] = 1;
                        q.push(v);
                    }
                }
                
                for(int j=1;j<=k;++j){
                    dis[v][j] = min(dis[u][j-1] , min(dis[u][j]+e[i].w , dis[v][j]));
                }
            }
        }
        int ans = inf;
        for(int i=0;i<=k;++i) ans = min(ans , dis[t][i]);
        printf("%d
    ",ans);
    }
    
    int main(){
        scanf("%d%d%d",&n,&m,&k);
        scanf("%d%d",&s,&t);
        memset(head,-1,sizeof head);
        for(int i=1;i<=m;++i){
            int u,v,w;scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);add(v,u,w);
        }
        spfa();
        return 0;
    }
    

    然鹅这个只有(90dpts),你还要一个(SLF)优化(大雾

    #include<cstdio>
    #include<queue>
    #include<cstring>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    
    int n,m,k;int s,t;
    
    const int MAXM = 50005;
    const int MAXN = 10005;
    
    inline ll read(){
        ll x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
        return x*f;
    }
    
    struct edge{
        int u,v,w,nxt;
    }e[MAXM<<1];int head[MAXN];int cnt=0;int dis[MAXN][15];int used[MAXN];int r[MAXN];
    
    inline void add(int u,int v,int w){
        e[++cnt].u = u;e[cnt].v = v;e[cnt].w = w;e[cnt].nxt = head[u];head[u] = cnt;
    }
    
    struct node{
        int p,used;
        node():p(0),used(0){}
        node(int a,int b):p(a),used(b){}
    };
    
    deque<node>q;
    inline void spfa(int x){
        memset(dis,inf,sizeof dis);
        for(int i=0;i<=k;++i) dis[x][i] = 0;
        q.push_back(node(x,0));
        while(!q.empty()){
            node u = q.front();q.pop_front();
            for(int i=head[u.p];i;i=e[i].nxt){
                int v = e[i].v;
                if(dis[v][u.used] > dis[u.p][u.used] + e[i].w){
                    dis[v][u.used] = dis[u.p][u.used] + e[i].w;
                    if(!q.empty() && dis[v][u.used] < dis[q.front().p][u.used]) q.push_front(node(v,u.used));else q.push_back(node(v,u.used));  
                }
                if(u.used+1 <= k && dis[v][u.used+1] > dis[u.p][u.used]){
                    dis[v][u.used+1] = dis[u.p][u.used];
                    if(!q.empty() && dis[v][u.used+1] < dis[q.front().p][u.used]) q.push_front(node(v,u.used+1));else q.push_back(node(v,u.used+1));  
                }
            }
        }
    }
    
    int main(){
        n=read();m=read();k=read();
        s = read();t = read();s++;t++;
        for(int i=1;i<=m;++i){
            int u,v,w;u = read();v = read();w = read();
            u++;v++;
            add(u,v,w);add(v,u,w);
        }
        spfa(s);
        int ans = inf;
        for(int i=0;i<=k;++i) ans = min(ans , dis[t][i]);
        printf("%d",ans);
        return 0;
    }
    
  • 相关阅读:
    python解析本地HTML文件
    爬取潇湘书院首页侧边栏
    Python文件的读取写入操作
    Python错误和异常
    Python字典
    python列表
    电文加密小程序
    课后练习题随笔(一)
    Redis基础操作
    Django学习_BBS开发
  • 原文地址:https://www.cnblogs.com/lajioj/p/9562650.html
Copyright © 2020-2023  润新知