luoguP2939 [USACO09FEB]改造路Revamping Trails

约翰一共有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;
}
 

posted @ 2018-02-22 16:30  小蒟蒻ysn  阅读(120)  评论(0编辑  收藏  举报