G. Bicycles

G. Bicycles

All of Slavic's friends are planning to travel from the place where they live to a party using their bikes. And they all have a bike except Slavic. There are n cities through which they can travel. They all live in the city 1 and want to go to the party located in the city n. The map of cities can be seen as an undirected graph with n nodes and m edges. Edge i connects cities ui and vi and has a length of wi.

Slavic doesn't have a bike, but what he has is money. Every city has exactly one bike for sale. The bike in the i-th city has a slowness factor of si. Once Slavic buys a bike, he can use it whenever to travel from the city he is currently in to any neighboring city, by taking wisj time, considering he is traversing edge i using a bike j he owns.

Slavic can buy as many bikes as he wants as money isn't a problem for him. Since Slavic hates traveling by bike, he wants to get from his place to the party in the shortest amount of time possible. And, since his informatics skills are quite rusty, he asks you for help.

What's the shortest amount of time required for Slavic to travel from city 1 to city n? Slavic can't travel without a bike. It is guaranteed that it is possible for Slavic to travel from city 1 to any other city.

Input

The first line contains a single integer t (1t100) — the number of test cases. The description of the test cases follows.

The first line of each test case contains two space-separated integers n and m (2n1000; n1m1000) — the number of cities and the number of roads, respectively.

The i-th of the following m lines each contain three integers ui, vi, wi (1ui,vin, uivi; 1wi105), denoting that there is a road between cities ui and vi of length wi. The same pair of cities can be connected by more than one road.

The next line contains n integers s1,,sn (1si1000) — the slowness factor of each bike.

The sum of n over all test cases does not exceed 1000, and the sum of m over all test cases does not exceed 1000.

Additional constraint on the input: it is possible to travel from city 1 to any other city.

Output

For each test case, output a single integer denoting the shortest amount of time Slavic can reach city n starting from city 1.

Example

input

3
5 5
1 2 2
3 2 1
2 4 5
2 5 7
4 5 1
5 2 1 3 3
5 10
1 2 5
1 3 5
1 4 4
1 5 8
2 3 6
2 4 3
2 5 2
3 4 1
3 5 8
4 5 2
7 2 8 4 1
7 10
3 2 8
2 1 4
2 5 7
2 6 4
7 1 2
4 3 5
6 4 2
6 7 1
6 7 4
4 5 9
7 6 5 4 3 2 1

output

19
36
14

 

解题思路

  由于必须要有车才可以移动,因此在到达任意节点时必然骑着第 1n 中的一辆车。把这些车看作是一种状态,就可以考虑 dp 了。

  定义 f(u,j) 表示从 1u 且到达 u 时骑的是第 j 辆车的所有路径中权重的最小值。f(u,v) 可以转移到与 u 相邻的节点 vi,并且可以骑着原来的第 j 辆车或第 u 辆车来到达 vi,如下图:

  因此状态转移方程就是:

f(u,j)+sjwif(vi,j)f(u,j)+suwif(vi,u)

  容易发现状态转移的过程中会出现环,因此得到的不是一个拓扑图,但每条边的权重 sxwi 都是非负的,因此可以对这个图跑 Dijkstra 来求得每个状态的最小权重。其中初始状态为 f(1,1)=0,最后答案是 min1jn{f(n,j)}

  AC 代码如下,时间复杂度为 O(nmlognm)

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 1010, M = N * 2;

int w[N];
int head[N], e[M], wt[M], ne[M], idx;
LL dist[N][N];
bool vis[N][N];

void add(int u, int v, int w) {
    e[idx] = v, wt[idx] = w, ne[idx] = head[u], head[u] = idx++;
}

void solve() {
    int n, m;
    scanf("%d %d", &n, &m);
    idx = 0;
    memset(head, -1, sizeof(head));
    while (m--) {
        int u, v, w;
        scanf("%d %d %d", &u, &v, &w);
        add(u, v, w), add(v, u, w);
    }
    for (int i = 1; i <= n; i++) {
        scanf("%d", w + i);
    }
    memset(dist, 0x3f, sizeof(dist));
    dist[1][1] = 0;
    priority_queue<tuple<LL, int, int>> pq;
    pq.push(make_tuple(0, 1, 1));
    memset(vis, 0, sizeof(vis));
    while (!pq.empty()) {
        int x = get<1>(pq.top()), y = get<2>(pq.top());
        pq.pop();
        if (vis[x][y]) continue;
        vis[x][y] = true;
        for (int i = head[x]; i != -1; i = ne[i]) {
            if (dist[e[i]][y] > dist[x][y] + w[y] * wt[i]) {
                dist[e[i]][y] = dist[x][y] + w[y] * wt[i];
                pq.push(make_tuple(-dist[e[i]][y], e[i], y));
            }
            if (dist[e[i]][x] > dist[x][y] + w[x] * wt[i]) {
                dist[e[i]][x] = dist[x][y] + w[x] * wt[i];
                pq.push(make_tuple(-dist[e[i]][x], e[i], x));
            }
        }
    }
    LL ret = 1e18;
    for (int i = 1; i <= n; i++) {
        ret = min(ret, dist[n][i]);
    }
    printf("%lld\n", ret);
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        solve();
    }
    
    return 0;
}

  同类题型可参考:[TJOI2019] 大中锋的游乐场速度限制

 

参考资料

  Codeforces Round 918 (Div. 4) Editorial:https://codeforces.com/blog/entry/123952

posted @   onlyblues  阅读(128)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示