HDU - 4725 The Shortest Path in Nya Graph(最短路+思维建图)


图论


传送门

题意:在一个空间中有一个N层图,每一层上分布着一些点(N个点),一层上有多个点
     或者没有点,一次只能从第i层跳到第i+1或者i-1,权值为w,现在给出一些有权边,
     问从1到n点的最短路
分析:很明显是最短路,关键在于怎么建图,这就涉及到层与点建边,层与层建边,每一个相邻
      层都可以建边。  
      如图:黑色为题给出的无向边,首先我们可以在每一层建立一个源点Si,然后对于这一
      层的每个点i与该源点建一条有向边(Si-->i),且这一层的每个点i需要与上一层和下一层
      的源点Si+1,Si-1,都要建有向边(i-->Si+1,i-->Si-1;最后就是两两相邻层之间建无
      向边

在这里插入图片描述

#include <set>
#include <map>
#include <list>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <bitset>
#include <vector>
#include<cstring>
#include <stdio.h>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline int read(){int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;}
const int maxn = 1e6+5;
int n,m,c;
int tot,head[maxn];
ll dis[maxn];
bool vis[maxn];
struct Edge{
    int to,next,val;
}edge[maxn];
ll inf=1e17+5;
struct node{
    ll dis;int pos;
    bool operator<(const node &x)const {
        return x.dis<dis;
    }
};
void add_edge(int u,int v,int w)
{
    edge[tot].to=v;
    edge[tot].next=head[u];
    edge[tot].val=w;
    head[u]=tot++;
}
void Dijskra(int s)
{
    priority_queue<node>q;
    memset(vis,false,sizeof(vis));

    for(int i=0;i<maxn;i++) dis[i]=inf;

    q.push({0,s});
    dis[s]=0;

    while (!q.empty())
    {
        int x=q.top().pos; q.pop();
        if(vis[x]) continue; vis[x]=true;
        for(int i=head[x];i!=-1;i=edge[i].next){
            int y=edge[i].to;
            if(dis[y]>dis[x]+(ll)edge[i].val){
                dis[y]=dis[x]+(ll)edge[i].val;
                if(!vis[y]) q.push({dis[y],y});
            }
        }
    }
}
struct Node{
    int pos,g;
}point[maxn];
bool cmp(Node x,Node y){
    return x.g<y.g;
}
int main()
{
    int t=read(),cas=0;
    while (t--)
    {
        tot=0;
        memset(head,-1,sizeof(head));
        n=read(),m=read(),c=read();
//        for(int i=1;i<=n;i++) point[i].g=read(),point[i].pos=i;
        for(int i=1;i<=n;i++)
        {
            int post=read();
                    add_edge(post+n,i,0);
            if(post<n) add_edge(i,post+n+1,c);
            if(post>1) add_edge(i,post+n-1,c);
        }
        for(int i=1;i<=m;i++){
            int u=read(),v=read(),w=read();
            add_edge(u,v,w);
            add_edge(v,u,w);
        }
//        int Maxedge=1e5+5;

//        for(int i=Maxedge;i<Maxedge+n;i++)
//            add_edge(i,i+1,c),add_edge(i+1,i,c);
//
//        sort(point+1,point+n+1,cmp);
//
//        int p=1;
//        for(int i=1;i<=n;i++){
//            int x=point[i].pos;
//
//            if(point[i].g!=p) Maxedge++,p++;
//
//            add_edge(Maxedge,point[i].pos,0);
//
//            if(Maxedge-1>=100005)
//                add_edge(point[i].pos,Maxedge-1,c);
//            if(Maxedge+1<=100005+n)
//                add_edge(point[i].pos,Maxedge+1,c);
//        }

        Dijskra(1);

        printf("Case #%d: ",++cas);
        if(dis[n]==inf) puts("-1");
        else printf("%lld\n",dis[n]);

    }
    return 0;
}
/*

3
3 3 3
1 3 2
1 2 2
2 3 2
1 3 4

1
3 2 1
1 2 1
1 3 10
2 3 4

 */```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值