1. 程式人生 > >2018南京網路賽 L Magical Girl Haze(最短路、堆、狀態轉移)

2018南京網路賽 L Magical Girl Haze(最短路、堆、狀態轉移)

我們設定dis[i][k]表示走到第i號點,免費經過了k條邊的最短路。 
對於我們當前找到的終點,嘗試起點的狀態去更新,不選擇此條邊免費的狀態和選擇此條邊免費的狀態,再將這兩個狀態壓入佇列去更新可以到達的其他狀態。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<set>
#define maxn 200005
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define LL long long
#define ev 2.71828182
using namespace std;
const double PI=acos(-1.0);

int t,n,m,k;
struct node
{
   int from,cs;
   LL w;
   friend bool operator <(node a,node b)
   {
      return a.w>b.w;
   }
};
struct knode
{
   int to,w;
};
vector<knode>v[maxn];
int dis[maxn][20];//dis[i][k]表示走到i點,k條邊置0時的最短距離
bool book[maxn][20];
void dijkstra()
{
   memset(dis,0x3f,sizeof(dis));
   memset(book,false,sizeof(book));
   priority_queue<node>q;
   node h={1,0,0};
   q.push(h);
   while(!q.empty())
   {
      node t=q.top();
      q.pop();
      if(book[t.from][t.cs])
         continue;
      book[t.from][t.cs]=true;
      for(int i=0;i<v[t.from].size();i++)
      {
         int mb=v[t.from][i].to;
         int bw=v[t.from][i].w;
         if(dis[mb][t.cs]>t.w+bw)
         {
            dis[mb][t.cs]=t.w+bw;
            q.push(node{mb,t.cs,dis[mb][t.cs]});
         }
         if(t.cs+1<=k)
         {
            if(dis[mb][t.cs+1]>t.w+0)
            {
               dis[mb][t.cs+1]=t.w;
               q.push(node{mb,t.cs+1,dis[mb][t.cs+1]});
            }
         }
      }
   }
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
       cin>>n>>m>>k;
       for(int i=0;i<maxn;i++)
         v[i].clear();
       for(int i=0;i<m;i++)
       {
          int a,b,c;
          cin>>a>>b>>c;
          knode z;
          z.to=b;z.w=c;
          v[a].push_back(z);
       }
       dijkstra();
       cout << dis[n][k] << endl;
    }
    return 0;
}