C HDU - 4725

最短路裸题 建图较难

点点之间的路径很好建立,但不同层之间的点的路径很难建立。

通过 点->层->层->点 这样走即可实现不同层之间的点的路径的建立

但我们要注意:点->层->层->点 点到层,不能直接到该层,要到上一层,或者下一层,否则可能最短路跑不出去。

数据范围1e5,我们再用1e5来建立,点层,层层的路径,比如,1代表第一个点,n+1就是第一层。

2e5的数据范围,走spfa应该可以,我是用了 dijstrak+堆优化 ,最近刚学QWQ
我时间比spfa多,应该是我用push_back()存图的缘故。

代码如下:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define fo1(a,b) for(int a=0;a<b;++a)
#define fo2(a,b) for(int a=1;a<=b;++a)
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=2e5+5;
const int mod=1e9+7;
const double eps=1e-9;
struct Edge{
    int v,w;
    Edge(int _v,int _w):
        v(_v),w(_w){}
};
struct Node{
    int index,val;
    Node(int _index=0,int _val=0):
        index(_index),val(_val){}
    bool operator <(const Node &b) const{
        return val>b.val;
    }
};
vector <Edge> p[maxn];
int t,n,m,c,dis[maxn],a[maxn];
bool vis[maxn],f[maxn];
void Dijkstra(){
     mem(vis,0);
     fo2(i,2*n)
        dis[i]=inf;
     priority_queue <Node> q;
     dis[1]=0;
     q.push(Node(1,0));
     while(!q.empty()){
        Node te=q.top();
        q.pop();
        int u=te.index;
        if(vis[u])
            continue;
        vis[u]=1;
        fo1(i,p[u].size()){
            int v=p[u][i].v;
            int w=p[u][i].w;
            if(!vis[v]&&dis[v]>dis[u]+w){
                dis[v]=dis[u]+w;
                q.push(Node(v,dis[v]));
            }
        }
     }
}
int main()
{
    scanf("%d",&t);
    fo2(l,t){
        mem(f,0);
        fo2(i,2*n)
        p[i].clear();
        scanf("%d%d%d",&n,&m,&c);
        fo2(i,n){
            scanf("%d",&a[i]);
            f[a[i]]=1;
        }
        int u,v,w;
        fo2(i,m){
            scanf("%d%d%d",&u,&v,&w);
            p[u].push_back(Edge(v,w));
            p[v].push_back(Edge(u,w));
        }
        // f and f
        fo2(i,n){
            if(f[i]&&f[i+1]){
                p[i+n].push_back(Edge(i+1+n,c));
                p[i+1+n].push_back(Edge(i+n,c));
            }
        }
        // p and f
        fo2(i,n){
            //p[i].push_back(Edge(a[i]+n,0));
            p[a[i]+n].push_back(Edge(i,0));
            if(a[i]>1)p[i].push_back(Edge(a[i]-1+n,c));
            if(a[i]<n)p[i].push_back(Edge(a[i]+1+n,c));
        }
        Dijkstra();
        int ans=-1;
        if(dis[n]!=inf)
            ans=dis[n];
        printf("Case #%d: %d\n",l,ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值