分层图最短路

1.单源最短路径+k次瞬间转移(路径值为0) 

spfa版本,注意是单向边啊啊

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
using namespace std;

const int M=10050;
const int K=15;
const int N=10050;
const int inf=0x3f3f3f3f;

int head[N],tot;
struct node{int v,w,next;}e[M<<1];
void insert(int u,int v,int w){
    e[++tot]=(node){v,w,head[u]};head[u]=tot;} 
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;}
int n,m,k;

int dis[K][N],vis[K][N];

int spfa(){
    rep(i,0,k)rep(j,1,n) dis[i][j]=inf;
    memset(vis,0,sizeof vis);
    rep(i,0,k) dis[i][1]=0;
    queue<pair<int,int> > q;q.push(make_pair(1,0));
    
    while(!q.empty()){
        int u=q.front().first,t=q.front().second;
        q.pop();vis[t][u]=0;
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].v,w=e[i].w;
            if(dis[t][u]+w<dis[t][v]){
                dis[t][v]=dis[t][u]+w;
                if(!vis[t][v]) vis[t][v]=1,q.push(make_pair(v,t));}
            if(dis[t][u]<dis[t+1][v]&&t<k){
                dis[t+1][v]=dis[t][u];
                if(!vis[t+1][v]) vis[t+1][v]=1,q.push(make_pair(v,t+1));}
        }
    }int ans=inf;
    rep(i,0,k) ans=min(ans,dis[i][n]);return ans;
}
int main(){
    freopen("through.in","r",stdin);
    freopen("through.out","w",stdout);
    n=read(),m=read(),k=read();
    rep(i,1,m){int u=read(),v=read(),w=read();insert(u,v,w);}
    printf("%d\n",spfa());return 0;
}

 2.SHOI2012 回家的路

建图的时候按照交汇点建图+起点和终点,由于只有xy两个维度所以直接拆点,在换乘处建立1的边即可

https://www.luogu.org/record/show?rid=10855025

 

posted @ 2018-09-17 14:47  ASDIC减除  阅读(137)  评论(0编辑  收藏  举报