[BZOJ5511][最短路]TJOI2019:大中锋的游乐场

BZOJ5511

水题

dijkstra加一维

Code:

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int res=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
    while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
    return res*f;
}
const int N=1e4+5,M=1e5+5;
int vis[M<<1],head[N],nxt[M<<1],c[M<<1],tot=0;
int pt[N][30],d[N][30],kd[N];
struct sp{
    int val,node,id;
    sp(int a,int b,int c){val=a,node=b,id=c;}
    friend inline bool operator < (const sp &x,const sp &y){return x.val>y.val;}
};
priority_queue<sp>q;
int n,m,k;
inline void add(int x,int y,int z){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;c[tot]=z;}
inline void dijkstra(int S,int T){
    for(int i=1;i<=n;i++) for(int j=0;j<=2*k;j++) d[i][j]=(1<<30);
    d[S][k+kd[S]]=0;
    q.push(sp(d[S][k+kd[S]],S,k+kd[S]));
    while(!q.empty()){
        sp now=q.top();q.pop();
        int num=now.id,nd=now.node;
        if(pt[nd][num]) continue;
        pt[nd][num]=1;
        for(int i=head[nd];i;i=nxt[i]){
            int y=vis[i],z=c[i];
            if(num+kd[y]<0 || num+kd[y]>2*k) continue;
            if(d[y][num+kd[y]]>d[now.node][num]+z){
                d[y][num+kd[y]]=d[now.node][num]+z;
                q.push(sp(d[y][num+kd[y]],y,num+kd[y]));
            }
        }
    }
}
int main(){
    int t=read();
    while(t--){
        tot=0;
        memset(head,0,sizeof(head));
        memset(pt,0,sizeof(pt));
        n=read();m=read();k=read();
        for(int i=1;i<=n;i++){
            kd[i]=read();
            if(kd[i]==2) kd[i]=-1;
        }
        for(int x,y,z,i=1;i<=m;i++){
            x=read(),y=read(),z=read();
            add(x,y,z);add(y,x,z);
        }
        int s=read(),t=read();
        dijkstra(s,t);
        int ans=(1<<30);
        for(int i=0;i<=2*k;i++) ans=min(ans,d[t][i]);
        cout<<(ans==(1<<30)?-1:ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值