[USACO15JAN]Cow Routing S 题解

[USACO15JAN]Cow Routing S 题解

题意很简单,不用多说。

先来看如何建边:因为一条航线一次性可以经过多个城市,还可以反复上下飞机。所以我们枚举一条航线里的每两个城市进行连边,边权都相等。

因为题目还要求经过几条边,所以我们在建边的时候记录下这条边起点、终点、边权、途径的城市个数。然后跑一遍 Dijkstra 就行。

其他注意事项:

除了最短路用的记录花费的数组,还需要开一个记录保证花费最小的情况下经过最小边数的数组。

因为建边比较多,前向星数组要开很大。

Code

#include <iostream>
#include <cstring>
#include <bitset>
#include <queue>

using namespace std;

const int N = 1e3 + 5, M = 5e6 + 5;

struct node
{
    long long dis;
    int road, u;
    bool operator > (const node &x) const {return dis == x.dis ? road > x.road : dis > x.dis;}
};

priority_queue<node, vector<node>, greater<node>> p;
int head[N], to[M], we[M], ne[M], c[M], idx = 1;
int s, t, n, a[N], road[N];
long long dist[N];
bitset<N> st;

void add(int u, int v, int w, int cnt)
{
    c[idx] = cnt;
    to[idx] = v;
    we[idx] = w;
    ne[idx] = head[u];
    head[u] = idx ++ ;
}

void Dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    memset(road, 0x3f, sizeof road);
    road[s] = dist[s] = 0;
    p.push({0, 0, s});

    while (!p.empty())
    {
        int u = p.top().u;
        p.pop();

        if (st[u]) continue;
        st[u] = true;

        for (int i = head[u]; i; i = ne[i])
        {
            int v = to[i], w = we[i], cnt = c[i];
            if (dist[v] > dist[u] + w)
            {
                dist[v] = dist[u] + w;
                road[v] = road[u] + cnt;
                p.push({dist[v], road[v], v});
            }
            else if (dist[v] == dist[u] + w && road[v] > road[u] + cnt)
            {
                road[v] = road[u] + cnt;
                p.push({dist[v], road[v], v});
            }
        }
    }
}

int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> s >> t >> n;

    int w, cnt;
    for (int i = 1; i <= n; i = i ++ )
    {
        cin >> w >> cnt;
        for (int j = 1; j <= cnt; j = j ++ )
        {
            cin >> a[j];
            for (int k = 1; k < j; k = k ++ ) add(a[k], a[j], w, j - k); // 经过几个城市
        }
    }

    Dijkstra();

    if (dist[t] == 0x3f3f3f3f3f3f3f3f) printf("-1 -1\n");
    else printf("%lld %d\n", dist[t], road[t]);
    return 0;
}

不懂可以私信我!

posted @ 2023-12-19 09:42  emo_male_god  阅读(26)  评论(0)    收藏  举报  来源