CCF 201609-4 交通规划_最短路

CCF 201609-4 交通规划 传送门

先放张图得瑟得瑟, 一遍过, so happy.

这里写图片描述

这是一道描述非常简单的题目, 看到题目就有点小开心, 觉得肯定能做出来的.

目的很清晰, 所有的点到首都的距离都是最短路, 那么最短路就要保存下来舍弃其他无用的边. 看数据范围, 就用SPFA算法了. 中心思想是记录最短路径+去除无用边

关键是一条路的最短路可能会有好几条, 那么应该怎么选呢? 如果停留在表面, 会觉得这道题目非常的复杂, 因为选出这些边, 似乎会影响后面的结果, 到底选哪些边? 计算机可不知道, 这里面一定有一个规则.

画张图, 仔细观察后会发现, 一个点可以有几个出度(也可以有0个), 但是只会有一个入度. 因为>1的话是无意义的. 那么很清晰了, 我们选出每个点入边里面最短的边即可, 也就是总共选出n - 1条边. 排个序来选就OK.

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;

struct Node {
    int to, w;
    Node (int t, int w) : to(t), w(w) {}
};

struct Edge {
    int from, to, w;
    Edge (int f, int t, int w) : from(f), to(t), w(w) {}
};

const int maxn = 10000 + 5;
const int INF = 0x3f3f3f3f;
vector<Node> G[maxn], last[maxn];
vector<Edge> edge;
int inque[maxn] = {}, n, m, dis[maxn], ans = 0;

bool cmp(Edge x, Edge y)
{
    if (x.to != y.to) return x.to < y.to;
    return x.w < y.w;
}

void SPFA()
{
    queue<int> Q;
    Q.push(1);
    inque[1] = true;
    dis[1] = 0;
    while (!Q.empty()) {
        int now = Q.front();
        inque[now] = false;
        Q.pop();
        for (int i = 0; i < G[now].size(); ++i) {
            int v = G[now][i].to, w = G[now][i].w;
            if (dis[v] == dis[now] + w) {
                last[v].push_back(Node(now, w));
            } else if (dis[v] > dis[now] + w) {
                last[v].clear();
                last[v].push_back(Node(now, w));
                dis[v] = dis[now] + w;
                if (!inque[v]) {
                    Q.push(v);
                    inque[v] = true;
                }
            }
        }
    }
}

int main()
{
    memset(dis, 0x3f, sizeof(dis));
    cin >> n >> m;
    for (int i = 1, u, v, w; i <= m; ++i) {
        cin >> u >> v >> w;
        G[u].push_back(Node(v, w));
        G[v].push_back(Node(u, w));
    }
    SPFA();
    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j < last[i].size(); ++j) {
            edge.push_back(Edge(last[i][j].to, i, last[i][j].w));
        }
    }
    sort(edge.begin(), edge.end(), cmp);
    int to = 2;
    for (int i = 0; i < edge.size(); ++i) {
        if (edge[i].to == to) {
            ans += edge[i].w;
            to++;
        }
    }
    cout << ans;
}

猜你喜欢

转载自blog.csdn.net/wjh2622075127/article/details/81530938
今日推荐