最短路,注意理解题意;
只要一个戒备点次数增加,所有的戒备点次数都增加;
#include<bits/stdc++.h> using namespace std; #define int long long const int inf=1e18; const int maxn=6000; int head[maxn],cnt,dis[maxn],n,m,k,a[maxn],vis[maxn]; struct edge{ int nx,to,w; }edge[maxn*maxn]; struct node{ int u,d,f;//f记录上一次戒备次数 friend bool operator < (const node &a,const node &b){ return a.d>b.d; } }; void add(int u,int v,int w) { edge[++cnt].nx=head[u]; edge[cnt].to=v; edge[cnt].w=w; head[u]=cnt; } void dij() { priority_queue<node> q; q.push({1,0,0}); dis[1]=0; while(!q.empty()) { node t=q.top();q.pop(); int u=t.u,h=t.f; int r=0; if(a[u]) r=1;//判断当前戒备,因为是从一个戒备点到达任意一点时,戒备次数才增加 for(int i=head[u];i;i=edge[i].nx) { int v=edge[i].to,w=edge[i].w; if(t.f+r<=k&&(dis[v]>dis[u]+w)) { dis[v]=dis[u]+w; q.push({v,dis[v],t.f+r}); } } } return; } signed main() { scanf("%lld%lld%lld",&n,&m,&k); for(int i=0;i<=n;i++) dis[i]=inf; for(int i=1;i<=n;i++) { cin>>a[i]; } for(int i=1;i<=m;i++) { int u,v,w; cin>>u>>v>>w; add(u,v,w),add(v,u,w); } dij(); if(dis[n]>=inf) cout<<-1<<endl; else cout<<dis[n]; }