Wannafly挑战赛2-B.Travel(最短路)

N座城市环形排列。其中第i座城市到第i+1座城市花费的时间为d[i]。特别地,第N座城市到第1座城市花费的时间为d[N]。这些道路都是双向的。M座传送门,第i座传送门连接了城市u[i]与城市v[i],并且需要花费w[i]的时间通过(可能有两座传送门连接了同一对城市,也有可能一座传送门连接了相同的两座城市)。这些传送门都是双向的。给出Q次查询,每次查询两点之间最短距离。 1NQ525011M201d[i]w[i]230

思路:考虑到M这么少,那么我们可以把查询中u到v的最短路转换成,u到x的最短路,x到v的最短路,类floyd的感觉。我们进行2*M次最短路,每次更新属于传送门的某个端点为起点的最短距离,dp[i][j]:表明传送门端点i到城市J的最短距离,答案就是 min{dp[i][u]dp[i][v]}1iN

#include <bits/stdc++.h>
using namespace std;
const int maxn = 52501 + 5;
const long long INF = 1e17;
typedef pair<int, int>pii;
vector<pii>G[maxn];

vector<int>point;
int n, m;
int inq[maxn];
long long sum[maxn], dist[50][maxn];

void spfa(int sx)
{

    for(int i = 1; i <= n; i++)  inq[i] = 0, dist[sx][i] = INF;
    queue<int>que;
    int val = point[sx];
    que.push(val);
    inq[val] = 1, dist[sx][val] = 0;

    while(que.size())
    {
        int cur = que.front();que.pop();
        inq[cur] = 0;
        for(auto o : G[cur])
        {
            int to = o.first, cost = o.second;
            if(dist[sx][to] > dist[sx][cur] + cost)
            {
                dist[sx][to] = dist[sx][cur] + cost;
                if(inq[to] == 0)    que.push(to), inq[to] = 1;
            }
        }
    }
}
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++)
    {
        int x;
        scanf("%d", &x);
        G[i].push_back({i % n + 1, x});
        G[i % n + 1].push_back({i, x});
        sum[i] = sum[i - 1] + x;
    }
    for(int i = 0; i < m; i++)
    {
        int x, y, w;
        scanf("%d%d%d", &x, &y, &w);
        G[x].push_back({y, w});
        G[y].push_back({x, w});
        point.push_back(x);
        point.push_back(y);
    }
    sort(point.begin(), point.end());
    point.resize(unique(point.begin(),point.end()) - point.begin());

    for(int i = 0; i < point.size(); i++)    spfa(i);
    int q;
    scanf("%d", &q);
    for(int i = 0; i < q; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        long long temp = abs(sum[x - 1] - sum[y - 1]);
        long long ans = min(temp, sum[n] - temp);
        for(int i = 0; i < point.size(); i++)
        {
            ans = min(ans, dist[i][x] + dist[i][y]);
        }
        printf("%lld\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_29556211/article/details/78541104