1. 程式人生 > >luoguP2939 [USACO09FEB]改造路Revamping Trails

luoguP2939 [USACO09FEB]改造路Revamping Trails

body line oid 通過 rail for dijstra emp sin

約翰一共有N)個牧場.由M條布滿塵埃的小徑連接.小徑可 以雙向通行.每天早上約翰從牧場1出發到牧場N去給奶牛檢查身體.

通過每條小徑都需要消耗一定的時間.約翰打算升級其中K條小徑,使之成為高 速公路.在高速公路上的通行幾乎是瞬間完成的,所以高速公路的通行時間為0.

請幫助約翰決定對哪些小徑進行升級,使他每天早上到牧場W花的時間最少.輸出這個最少 的時間.

分層圖DP,啟發良多

1、遠離SPFA,Dijstra+堆穩定多了

2、要在Dijstra中Dp,堆中必須包含三要素:當前點、層數、距離,缺一不可

3、若當前點更新過,可以continue

4、大根堆中排序標準要倒著寫
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define re register
#define il inline
#define ll long long
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
const int N=100050;
int n,m,h[N],cnt,k,dp[N][30];
bool vis[N][30];
struct Edge
{
int to,next,w;
}e[N<<2];
struct node
{
int u,t,dis;
bool operator < (const node &x) const
{return dis>x.dis;}
};
priority_queue<node>Q;
il void add(re int u,re int v,re int w)
{
e[++cnt]=(Edge){v,h[u],w};h[u]=cnt;
}
il int gi()
{
re int x=0,t=1;
re char ch=getchar();
while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘)) ch=getchar();
if(ch==‘-‘) t=-1,ch=getchar();
while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-48,ch=getchar();
return x*t;
}
il void SPFA()
{
memset(dp,63,sizeof(dp));
dp[1][0]=0;Q.push((node){1,0,0});
while(!Q.empty())
{
re int u=Q.top().u,j=Q.top().t;Q.pop();
if(vis[u][j]) continue;vis[u][j]=1;
for(re int i=h[u];i;i=e[i].next)
{
re int v=e[i].to;
if(j+1<=k)
if(dp[v][j+1]>dp[u][j])
{
dp[v][j+1]=dp[u][j];
Q.push((node){v,j+1,dp[v][j+1]});
}
if(dp[v][j]>dp[u][j]+e[i].w)
{
dp[v][j]=dp[u][j]+e[i].w;
Q.push((node){v,j,dp[v][j]});
}
}
}
}
int main()
{
n=gi();m=gi();k=gi();
fp(i,1,m)
{
re int u=gi(),v=gi(),w=gi();
add(u,v,w);add(v,u,w);
}
SPFA();
printf("%d\n",dp[n][k]);
return 0;
}


luoguP2939 [USACO09FEB]改造路Revamping Trails