1. 程式人生 > >Magical Girl Haze(迪傑斯特拉+dp)

Magical Girl Haze(迪傑斯特拉+dp)

There are NN cities in the country, and MMdirectional roads from uu to v(1\le u, v\le n)v(1≤u,v≤n). Every road has a distance c_ici​. Haze is a Magical Girl that lives in City 11, she can choose no more than KK roads and make their distances become 00. Now she wants to go to City NN, please help her calculate the minimum distance.

Input

The first line has one integer T(1 \le T\le 5)T(1≤T≤5), then following TT cases.

For each test case, the first line has three integers N, MN,M and KK.

Then the following MM lines each line has three integers, describe a road, U_i, V_i, C_iUi​,Vi​,Ci​. There might be multiple edges between uu andvv.

It is guaranteed that N \le 100000, M \le 200000, K \le 10N≤100000,M≤200000,K≤10,
0 \le C_i \le 1e90≤Ci​≤1e9. There is at least one path between City 11 and City NN.

Output

For each test case, print the minimum distance.

樣例輸入複製

1
5 6 1
1 2 2
1 3 4
2 4 3
3 4 1
3 5 6
4 5 2

樣例輸出複製

3

題目來源

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <queue>
#define INF 0x3f3f3f3f3f3f3f3f
#define MAXN 200000
using namespace std;
/*  Dijkstar 演算法+堆優化 使用優先佇列優化,複雜度O(ElogE)
*   使用優先佇列優化Dijkstra演算法
*	複雜度O(ElogE)
*	注意對vector<Edge>E[MAXN]進行初始化後加邊
*/
long long  dis[MAXN][20];
bool vis[MAXN][20];
struct qnode          //這是為優先佇列服務的結構體
{
    int u;
    long long c;      //c表示的dis[i],即起點到i的距離
    int num;
    qnode(int _u=0,long long _c=0,int _num=0):u(_u),c(_c),num(_num){}
    bool operator <(const qnode &r)const  //c起排序作用,最短的先。
    {
        if(c!=r.c)  return c>r.c;
        else        return num>r.num;
    }
};
struct Node
{
   int v;
   long long w;  //w是指兩點的距離
   Node(int _v=0,long long _w=0):v(_v),w(_w){}
};
vector<Node> G[MAXN];
void init(int n)
{
     int i;
     for(i=0;i<=n;i++)
     G[i].clear();
     memset(vis,false,sizeof(vis));
     memset(dis,INF,sizeof(dis));
}
void addedge(int u,int v,int w)
{
    G[u].push_back(Node(v,w));
}
void dijkstra(int start,int n,int k) //點的編號從1開始
{
     int i;
     priority_queue<qnode>  que;
     while(!que.empty())
     que.pop();                //對於多組測試資料的話,就要不斷地清空
     dis[start][0]=0;
     que.push(qnode(start,0,0));
     qnode tmp;
     while(!que.empty())
     {
          tmp=que.top();
          que.pop();
          int u=tmp.u;
          int num=tmp.num;
          if(vis[u][num])    continue;  //因為是雙向圖嘛,所以vis標記是關鍵的
          vis[u][num]=true;             //這個vis標記的是當前在哪個結點,算的是起點到當前這個點的最短距離。
                                   //當以這點為轉達時就標記。因為他的最短距離已經在之前算過了,之前一定是最短
          for(i=0;i<G[u].size();i++)
          {
              int         v=G[u][i].v;
              long long   w=G[u][i].w;
              if(!vis[v][num]&&dis[v][num]>dis[u][num]+w)    //考慮同num狀態    ,因為總共就兩種狀態轉移,對當前邊取與不取0的討論
              {                                              //不取意味著num不變,取意味著num+1
                   dis[v][num]=dis[u][num]+w;
                   que.push(qnode(v,dis[v][num],num));
              }
              if(!vis[v][num+1]&&(num<k)&&(dis[v][num+1]>dis[u][num]))   //考慮同num+1狀態(轉態轉移時考慮的是 dis[u][num-1]與dis[v][num]的比較
              {                                                          //但演算法要寫num+1的
                  dis[v][num+1]=dis[u][num];
                  que.push(qnode(v,dis[v][num+1],num+1));
              }
          }
     }
}
int main()
{
    int n,m,k;
    int i;
    int u,v;
    long long w;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&k);
        init(n);
        for(i=0;i<m;i++)
        {
            scanf("%d%d%lld",&u,&v,&w);
            addedge(u,v,w);
        }
        dijkstra(1,n,k);
        printf("%lld\n",dis[n][k]);
    }
    return 0;
}