1. 程式人生 > >Nowcoder contest 370B Rinne Loves Graph 【分層圖最短路】

Nowcoder contest 370B Rinne Loves Graph 【分層圖最短路】

typedef spa head 下一個 bsp 分析 continue edge org

<題目鏈接>

題目大意:

Island 是有一些奇怪的城鎮和道路構成的(題目需要,遊戲黨勿噴),有些城鎮之間用雙向道路連接起來了,且每條道路有它自己的距離。但是有一些城鎮已經被派兵戒嚴,雖然主角可以逆天改命強闖,但是為了體驗該遊戲的平衡性,他們只能穿過不超過 K 次被戒嚴的城鎮。 定義“穿過”:從一個戒嚴的點出發到達任意一個點,都會使得次數加1

現在他們想從 1 號城鎮最快的走到 n 號城鎮(即出口),現在他們想讓你告訴他們最短需要走多少路。
2n800,1m4000,1k10,1w10^6

解題分析:

本題很明顯是一道分成圖最短路的題主要的就是怎麽處理"穿過"K個點,我是通過在最短路松弛過程中,判斷下一個點是否是封鎖點,是的話,就要利用分層圖的性質進行松弛。因為題目規定的是穿過k個封鎖點,所以我們需要對起點和終點進行處理。如果起點是封鎖點,那麽k--,如果終點是封鎖點k++,因為起點是一定要穿過的,而終點穿不過。

#include <bits/stdc++.h>
using namespace std;

#define clr(a,b) memset(a,b,sizeof(a))
#define rep(i,s,t) for(int i=s;i<=t;i++)
typedef 
long long ll; const int N = 805, M = 4005; int n,m,k,cnt; int isgo[N],head[N]; template<typename T> inline void read(T&x){ x=0;int f=1;char ch=getchar(); while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar(); } while(ch>=0 && ch<=9){x=x*10+ch-0;ch=getchar();} x
*=f; } struct Edge{ int to,nxt;ll w; }edge[M<<1]; struct Node{ int loc,lev;ll dist; Node(int _loc=0,int _lev=0,ll _dist=0):loc(_loc),lev(_lev),dist(_dist){} bool operator < (const Node &tmp)const{ return dist>tmp.dist; } }node[N][15]; int vis[N][15]; inline void init(){ cnt=0;clr(head,-1); } inline void add(int u,int v,ll w){ edge[++cnt].to=v,edge[cnt].nxt=head[u]; edge[cnt].w=w;head[u]=cnt; } void Dij(){ rep(i,1,n) rep(j,0,k){ node[i][j].loc=i,node[i][j].lev=j; node[i][j].dist=1e18;vis[i][j]=0; } priority_queue<Node>q; node[1][0].dist=0; q.push(node[1][0]); while(!q.empty()){ Node now=q.top();q.pop(); int loc=now.loc,lev=now.lev; if(vis[loc][lev])continue; vis[loc][lev]=1; for(int i=head[loc];~i;i=edge[i].nxt){ int v=edge[i].to;ll cost=edge[i].w; if(!isgo[v] && node[v][lev].dist>node[loc][lev].dist+cost){ //進行同層次建進行正常的松弛 node[v][lev].dist=node[loc][lev].dist+cost; q.push(Node(v,lev,node[v][lev].dist)); } if(isgo[v] && (lev+1)<=k && node[v][lev+1].dist>node[loc][lev].dist+cost){ //不是封鎖點的就沒有必要利用分層圖進行松弛,因為在正常的一層就已經松弛了 node[v][lev+1].dist=node[loc][lev].dist+cost; q.push(Node(v,lev+1,node[v][lev].dist)); } } } } int main(){ init(); read(n);read(m);read(k); rep(i,1,n) read(isgo[i]); rep(i,1,m){ int u,v;ll w;read(u);read(v);read(w); add(u,v,w);add(v,u,w); } if(isgo[1])k--; if(isgo[n])k++; Dij(); ll ans=1e18;rep(i,0,k)ans=min(ans,node[n][i].dist); printf("%lld\n",ans); }

Nowcoder contest 370B Rinne Loves Graph 【分層圖最短路】