[P4568][JLOI2011] 飞行路线 (分层图+最短路)

题意:有n个城市,m条航线,每条航线都有一个权值,并且还多了k次免费航行的机会,求1~n的最短路;

做法:分层图+最短路;

1.分层图;因为多了k次免费航行,所以可以考虑建出k+1个图,然后跑一遍最短路;

2.最短路;既然能写分层图,那么最短路应该都会了吧,可以用 dijkstra 或 SPFA ;

附上代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define pr pair<int ,int >
using namespace std;
const int N = 5e5+10;
const int inf = 0x3f3f3f3f;

inline int read(){
    int ref=0,x=1;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) ref=ref*10+ch-'0',ch=getchar();
    return ref*x;
}

int n,m,k,s,t;
struct edge{
    int next,to,w;
}a[N<<4];
int head[N],cnt;
int dis[N<<4],vis[N<<4];
int ans=inf;

void add(int u,int v,int w){
    a[++cnt]=(edge){head[u],v,w};
    head[u]=cnt;
}

void dijkstra(int x){
    memset(dis,inf,sizeof(dis));
    priority_queue<pr ,vector<pr> ,greater<pr> > q;
    q.push(make_pair(0,x));
    dis[x]=0;
    while(!q.empty()){
        int temp=q.top().second;
        q.pop();
        if(vis[temp]) continue;
        vis[temp]=1;
        for(int i=head[temp];i;i=a[i].next){
            int v=a[i].to;
            if(dis[v]>dis[temp]+a[i].w){
                dis[v]=dis[temp]+a[i].w;
                q.push(make_pair(dis[v],v));
            }
        }
    }
}

int main()
{
    n=read(),m=read(),k=read();
    s=read(),t=read();
    for(int i=1;i<=m;++i){
        int x,y,z;
        x=read(),y=read(),z=read();
        add(x,y,z),add(y,x,z);
        for(int j=1;j<=k;++j){
            add(x+j*n,y+j*n,z);
            add(y+j*n,x+j*n,z);
            add(x+(j-1)*n,y+j*n,0);
            add(y+(j-1)*n,x+j*n,0);
        }
    }
    dijkstra(s);
    for(int i=0;i<=k;++i) ans=min(ans,dis[t+i*n]);
    printf("%d",ans);
    return 0;
}

 

原文地址:https://www.cnblogs.com/nnezgy/p/11479276.html