hdu 4725 带层的最短路

题意:n个点,m条边,以及相邻层之间移动的代价c,给出每个点所在的层数,以及m条边,

每条边有u,v,c,表示从节点u到v(无向),并且移动的代价 c ,问说从 1 到 n 的代价最小是多少。

参考 https://www.cnblogs.com/kuangbin/archive/2013/09/11/3315071.html

思路:

最短路。主要是建图。

N个点,然后有N层,要增加2*N个点。总共是3*N个点。

点1~N就是对应的实际的点1~N.  要求的就是1到N的最短路。

然后点N+1 ~ 3*N 是N层拆出出来的点。

第i层,入边到N+2*i-1, 出边从N+2*i 出来。(1<= i <= N)

N + 2*i    到  N + 2*(i+1)-1 加边长度为C. 表示从第i层到第j层。

N + 2*(i+1) 到 N + 2*i - 1 加边长度为C,表示第i+1层到第j层。

如果点i属于第u层,那么加边 i -> N + 2*u -1         N + 2*u ->i  长度都为0

就是说 点 x  与之对应的层点有2个, 到一个 a 入度为1,权值为0 ,一个 b 出度为1 权值为 0

由于层之间的移动, 假设y对应层和他是相邻的, 那么c,d   需要添加 a->d  和 c->b 两个边 

来表示于  x->a->d->y  y->c->b->a... 这样最短路也要是3*n  了

 

#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<cmath>
using namespace std;

#define ll long long
#define pb push_back
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair

const int N = 3e5+4;
const int INF = 1e9+3;


//https://www.cnblogs.com/kuangbin/archive/2013/09/11/3315071.html

struct node{
    int to,cost;
};
vector<node>V[N];
int d[N];
int n,m,c;
void add(int u,int v,int c){
    V[u].pb( node{v,c});
}
void dij(){

    for(int i=1;i<=n;++i)d[i]=INF;
    d[1]=0;
    priority_queue< pii , vector<pii> ,greater<pii> > Q;
    Q.push(mp(0,1));
    while(!Q.empty()){
        pii p =Q.top();Q.pop();
        int v= p.se;int val =p.fi;
        if(val>d[v])continue;
        for(int i=0;i<V[v].size();++i){
            node e= V[v][i];
            int u = e.to;
            if(d[u] > d[v]+e.cost){
                d[u] = d[v]+e.cost;   Q.push(mp(d[u],u));
            }
        }

    }

}

int main(){

    int t;
    cin>>t;
    int cnt=1;

    while(t--){
        scanf("%d %d %d",&n,&m,&c);
        for(int i=1;i<=n*3;++i)V[i].clear();

        for(int i=1;i<=n;++i){
            int l;
            scanf("%d",&l);
            add(i,n+2*l-1,0);
            add(n+2*l,i,0);
        }

        for(int i=1;i<n;++i){
            add( n+2*i-1,n+2*(i+1),c );
            add(n +2*(i+1)-1 , n+2*i,c);
        }
        while(m--){
            int u,v,d;
            scanf("%d %d %d",&u,&v,&d);
            add(u,v,d);
            add(v,u,d);
        }

        n*=3;

        dij();

        n/=3;

        printf("Case #%d: ",cnt++);
        if(d[n]==INF)printf("-1\n");
        else cout<<d[n]<<endl;
    }

    return 0;
}

 

posted on 2018-10-08 20:38  Helpp  阅读(118)  评论(0编辑  收藏  举报

导航