这道题的可以用分层图来理解,分层图就是同一个图在z轴多了一个一样的图,每一层可以代表休息的次数,最下面为0层,这样bfs的时候,在当前节点休息就相当于优先队列中的上一个点连接到第0层的当前点,在当前节点不休息,就相当于有限队列中的上一个点连接到更高一层的当前点,这样就建立了一个立体的图,在用最短路的求法就可以解决了。
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
typedef long long ll;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;

void solve() {
    int n,m,k;
    cin>>n>>m>>k;
    vector<int> a(n+5);
    vector<vector<int>> g(n+5);
    for (int i = 1; i <= n; ++i) {
        cin>>a[i];
    }
    for (int i = 1; i <= m; ++i) {
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    //当前花费 节点 不休息的次数
    priority_queue<array<int,3>,vector<array<int,3>>,greater<>> q;
    vector<vector<int>> vis(n+5,vector<int>(k+5,0));
    vector<vector<int>> ans(n+5,vector<int>(k+5,1e18));
    //k不为0时,初始时队列需要放两种状态
    if(k != 0){ //如果k不等于0,则代表第一次可以直接不休息
        q.push({1,1,1});
        ans[1][1] = 1;
    }
    //放入在第一个点休息的状态
    q.push({a[1],1,0});
    ans[1][0] = a[1];
    while (!q.empty()){
        auto [cost,now,cnt] = q.top();
        q.pop();
        if(vis[now][cnt]){
            continue;
        }
        vis[now][cnt] = 1;
        for (auto it : g[now]) {
            if(ans[it][0] > cost + a[it]){
                ans[it][0] = cost + a[it];
                q.push({cost + a[it],it,0});
            }
            if(cnt + 1 <= k && ans[it][cnt+1] > cost + 1){
                ans[it][cnt + 1] = cost + 1;
                q.push({cost + 1,it,cnt+1});
            }
        }
    }
    int minans = 1e18;
    for (int i = 0; i <= k; ++i) {
        minans = min(minans,ans[n][i]);
    }
    cout<<minans<<endl;
}
signed main() {
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}