hdu (4396:多校第十场):又见spfa求各种状态的最短路

53 篇文章 0 订阅

   本题题意:为找到至少走K条边的最短路。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <string>
#define inf 1<<30
using namespace std;
const int N=5050;
struct Node
{
   int v;
   int len;
};
struct Que
{
   int num;
   int tim;
};
vector<Node>edge[N];
queue<Que>myqueue;

int n,m,s,t,k;
int dis[N][60];//dis[i][j]表示走了到达第i个节点走了j条路的最短路
int vis[N][60];//是否在队列中

int spfa()
{
    for(int i=1;i<=n;i++)
      for(int j=0;j<=k+1;j++)
        dis[i][j]=inf;
    while(!myqueue.empty())
       myqueue.pop();
    memset(vis,0,sizeof(vis));
    Que top;
    top.num=s;
    top.tim=0;
    dis[s][0]=0;
    vis[s][0]=1;
    myqueue.push(top);
    Que net;
    while(!myqueue.empty())
    {
      top=myqueue.front();
      myqueue.pop();
      int tim=top.tim;
      int u=top.num;
      vis[u][tim]=0;
      for(int i=0;i<edge[u].size();i++)
      {
          int v=edge[u][i].v;
          int le=edge[u][i].len;
          int nx;
          if(tim>k)
            nx=tim;
          else
            nx=tim+1;
          if(dis[v][nx]>dis[u][tim]+le)
          {
              dis[v][nx]=dis[u][tim]+le;
              if(!vis[v][nx])
              {
                  vis[v][nx]=1;
                  net.num=v;
                  net.tim=nx;
                  myqueue.push(net);
              }
          }
      }
    }
    if(dis[t][k]>=inf&&dis[t][k+1]>=inf)
    return -1;
    else
    return min(dis[t][k],dis[t][k+1]);
}

int main()
{
  int u,v,len;
  Node ne;
  while(scanf("%d%d",&n,&m)!=EOF)
  {
      for(int i=1;i<=n+2;i++)
        edge[i].clear();
       for(int i=1;i<=m;i++)
       {
          scanf("%d%d%d",&u,&v,&len);
           ne.len=len;
           ne.v=v;
           edge[u].push_back(ne);
           ne.v=u;
           edge[v].push_back(ne);
       }
       scanf("%d%d%d",&s,&t,&k);
       k=k%10==0?k/10:k/10+1;
       int ans=spfa();
       printf("%d\n",ans);
  }
  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值