HDU 4725 (The Shortest Path in Nya Graph)dijkstra

题意:
这是带层的点,从本层的点到上下一层的任何一个节点的权值为c,也有一些点与点之间的路径。主要是建图,建图结束跑一下dijkstra就可以了。
思路:
我们主要说一下建图。
我们可以把每个点的层数看成是一个节点从N+1开始标记。对于这个层数节点 我们对每个在这个层的点 建一条从层数节点出发到这个层的点权值为0有向边。
然后对每个点到他的上、下一层建一条权值为c的有向边。
最后再对m对点建边即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=5*1e5+10;
const int inf=0x3f3f3f3f;
int head[maxn];
int vis[maxn];
int dis[maxn];
int layer[maxn];
int vislay[maxn];
int cnt;
struct edge {
    int u,v,w,next;
}e[maxn];
struct qnode{
    int dist,num;
    friend bool operator < (qnode a, qnode b){
        return a.dist >b.dist;
    }
};

void init(){
    memset(vis,0,sizeof(vis));
    memset(dis,inf,sizeof(dis));
    memset(head,-1,sizeof(head));
    memset(vislay,0,sizeof(vislay));
}
void add_edge(int u,int v,int w){
    e[++cnt].u=u;e[cnt].v=v;e[cnt].w=w;e[cnt].next=head[u];head[u]=cnt;
}
int dijkstra(int b,int n){
    priority_queue<qnode>q;
    vis[b]=1;
    dis[b]=0;
    qnode now,temp;
    now.dist=dis[b];
    now.num=b;
    q.push(now);
    while(!q.empty()){
        now=q.top();
        q.pop();
        vis[now.num]=0;
        for(int i=head[now.num];i!=-1;i=e[i].next){
            if(dis[e[i].v]>dis[now.num]+e[i].w){
                dis[e[i].v]=dis[now.num]+e[i].w;
                if(!vis[e[i].v]){
                    temp.dist=dis[e[i].v];
                    temp.num=e[i].v;
                    q.push(temp);
                    vis[vis[e[i].v]]=1;
                }
            }
        }
    }
    return dis[n];
}
int main()
{
    int t,tt=0,n,m,c;
    scanf ("%d",&t);
    while(t--){
        cnt = 0;
        init();
        scanf("%d%d%d",&n,&m,&c);
        for(int i=1;i<=n;i++){
            scanf("%d",&layer[i]);
            vislay[layer[i]]=1;         //标记一下这个层数有没有点
        }
        for(int i=1;i<=n;i++){
            add_edge(layer[i]+n,i,0);     //自己的层数节点到自己建一条权值为0的边。
            if(layer[i]-1>0&&vislay[layer[i]-1]){
                add_edge(i,layer[i]+n-1,c);    //这个点可以到的下面建一条权值为c的边
            }
            if(layer[i]+1<=n&&vislay[layer[i]+1]){
                add_edge(i,layer[i]+n+1,c);   //这个点可以到的上面建一条权值为c的边
            }
        }
        for(int i=1;i<=m;i++){
            int uu,vv,ww;
            scanf("%d%d%d",&uu,&vv,&ww);
            add_edge(uu,vv,ww);
            add_edge(vv,uu,ww);
        }
        printf("Case #%d: ",++tt);
        int ans=dijkstra(1,n);
        if(ans==inf){
            printf("-1\n");
        }
        else{
            printf("%d\n",ans);
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值