其他分享
首页 > 其他分享> > 洛谷 4568 [JLOI2011]飞行路线

洛谷 4568 [JLOI2011]飞行路线

作者:互联网

题目

一个无向图,每条边都有花费,可以有\(k\)次挑选边去除花费的机会,问从指定起点到指定终点的最小花费


分析

考虑用分层最短路完成,也就是在同一层走需要花费,不同层走不用花费,最终走到最底层,然后需要建\(k\)层,再跑一个\(\text{Dijkstra}\)就可以了


代码

#include <cstdio>
#include <cctype>
#include <queue>
#include <cstring>
#define rr register
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int N=110011;
struct rec{
    int w,u;
    bool operator <(const rec &t)const{
        return w>t.w;
    }
};
struct node{int y,w,next;}e[N*20]; bool v[N];
int n,m,cnt,k,st,en,ans,ls[N],dis[N];
inline signed iut(){
    rr int ans=0; rr char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    return ans; 
}
inline void add(int x,int y,int w){e[++cnt]=(node){y,w,ls[x]},ls[x]=cnt;};
priority_queue<rec>q;
signed main(){
    n=iut(),m=iut(),k=iut(),st=iut()+1,en=iut()+1;
    for (rr int i=1;i<=m;++i){
        rr int x=iut()+1,y=iut()+1,w=iut();
        add(x,y,w),add(y,x,w);
        for (rr int j=1;j<=k;++j){
            add(x+j*n,y+j*n,w),add(x+j*n-n,y+j*n,0),
            add(y+j*n,x+j*n,w),add(y+j*n-n,x+j*n,0);
        }
    }
    memset(dis,42,sizeof(dis)),dis[st]=0;
    q.push((rec){0,st}),ans=dis[0];
    while (q.size()){
        rr rec t=q.top(); rr int x=t.u,now=t.w; q.pop();
        if (dis[x]!=now||v[x]) continue; v[x]=1;
        for (rr int i=ls[x];i;i=e[i].next)
        if (dis[e[i].y]>dis[x]+e[i].w){
            dis[e[i].y]=dis[x]+e[i].w;
            q.push((rec){dis[e[i].y],e[i].y});
        }
    }
    for (rr int i=0;i<=k;++i) ans=min(ans,dis[i*n+en]);
    return !printf("%d",ans);
}

标签:include,洛谷,rr,JLOI2011,int,花费,4568,iut,dis
来源: https://www.cnblogs.com/Spare-No-Effort/p/12197627.html