解题报告(因为不会所以写简略版版)

第一题构造dijkstra函数接收一个图(邻接表表示)和一个起点,返回从起点到所有其他节点的最短路径长度。算法使用优先队列(最小堆)来优化寻找最小距离,找到并输出,没找到则输出disjoint。代码如下:

#include <iostream>
#include <vector>
#include <queue>
#include <climits>

using namespace std;
struct Edge {
    int to;
    int time;
    Edge(int t, int tm) : to(t), time(tm) {}
};
vector<int> dijkstra(const vector<vector<Edge>>& graph, int start) {
    int n = graph.size();
    vector<int> dist(n, INT_MAX);
    dist[start] = 0;

    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
    pq.push({0, start});

    while (!pq.empty()) {
        int u = pq.top().second;
        int d = pq.top().first;
        pq.pop();

        if (d > dist[u]) continue;

        for (const Edge& edge : graph[u]) {
            int v = edge.to;
            int time = edge.time;

            if (dist[u] + time < dist[v]) {
                dist[v] = dist[u] + time;
                pq.push({dist[v], v});
            }
        }
    }

    return dist;
}

int main() {
    int n;
    while (cin >> n && n != 0) {
        vector<vector<Edge>> graph(n);
        for (int i = 0; i < n; ++i) {
            int numContacts;
            cin >> numContacts;
            for (int j = 0; j < numContacts; ++j) {
                int to, time;
                cin >> to >> time;
                graph[i].emplace_back(to - 1, time);
            }
        }

        int minMaxTime = INT_MAX;
        int startPerson = -1;

        // 尝试从每个股票经纪人开始传播谣言
        for (int i = 0; i < n; ++i) {
            vector<int> dist = dijkstra(graph, i);

            int maxTime = 0;
            bool isDisjoint = false;
            for (int j = 0; j < n; ++j) {
                if (dist[j] == INT_MAX) {
                    isDisjoint = true;
                    break;
                }
                maxTime = max(maxTime, dist[j]);
            }

            if (!isDisjoint && maxTime < minMaxTime) {
                minMaxTime = maxTime;
                startPerson = i;
            }
        }

        if (startPerson == -1) {
            cout << "disjoint" << endl;
        } else {
            cout << startPerson + 1 << " " << minMaxTime << endl;
        }
    }

    return 0;
}

第三题类似,代码如下:

#include <iostream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;

typedef long long ll;
typedef pair<ll, int> pii; // {distance, node}

const ll INF = LLONG_MAX;

void dijkstra(int start, const vector<vector<pii>>& graph, vector<ll>& dist) {
    int n = graph.size();
    dist.assign(n, INF);
    dist[start] = 0;

    priority_queue<pii, vector<pii>, greater<pii>> pq;
    pq.push({0, start});

    while (!pq.empty()) {
        ll d = pq.top().first;
        int u = pq.top().second;
        pq.pop();

        if (d > dist[u]) continue;

        for (const auto& edge : graph[u]) {
            int v = edge.second;
            ll w = edge.first;

            if (dist[u] + w < dist[v]) {
                dist[v] = dist[u] + w;
                pq.push({dist[v], v});
            }
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N;
    cin >> N;

    while (N--) {
        int P, Q;
        cin >> P >> Q;

        // Original graph: CCS (1) to all stations
        vector<vector<pii>> original(P + 1);
        // Reverse graph: All stations to CCS (1)
        vector<vector<pii>> reverse(P + 1);

        for (int i = 0; i < Q; ++i) {
            int u, v, w;
            cin >> u >> v >> w;
            original[u].push_back({w, v}); // Original edge
            reverse[v].push_back({w, u}); // Reverse edge
        }

        // Dijkstra from CCS to all stations
        vector<ll> dist_original(P + 1, INF);
        dijkstra(1, original, dist_original);

        // Dijkstra from all stations to CCS (using reverse graph)
        vector<ll> dist_reverse(P + 1, INF);
        dijkstra(1, reverse, dist_reverse);

        // Calculate total cost
        ll total_cost = 0;
        for (int i = 1; i <= P; ++i) {
            total_cost += dist_original[i] + dist_reverse[i];
        }

        cout << total_cost << "\n";
    }

    return 0;
}

第二题是树,但是要用dfs找到最远的节点。代码如下:

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

const int MAXN = 100005;
vector<int> tree[MAXN];
int maxDistance = 0;
int farthestNode = 0;

// DFS function to find the farthest node from the starting node
void dfs(int node, int parent, int distance) {
    if (distance > maxDistance) {
        maxDistance = distance;
        farthestNode = node;
    }
    for (int neighbor : tree[node]) {
        if (neighbor != parent) {
            dfs(neighbor, node, distance + 1);
        }
    }
}

int main() {
    int n;
    cin >> n;

    // Build the tree
    for (int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        tree[u].push_back(v);
        tree[v].push_back(u);
    }

    // First DFS to find the farthest node from node 1
    maxDistance = 0;
    farthestNode = 0;
    dfs(1, -1, 0);

    // Second DFS to find the farthest node from the node found in the first DFS
    maxDistance = 0;
    dfs(farthestNode, -1, 0);

    // The diameter is the maximum distance found in the second DFS
    cout << maxDistance << endl;

    return 0;
}

第四题也是类似,但我讲不明白,代码如下:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

const int MAXN = 1505;
vector<int> tree[MAXN];
int dp[MAXN][2];

void dfs(int u, int parent) {
    dp[u][0] = 0;
    dp[u][1] = 1;

    for (int v : tree[u]) {
        if (v == parent) continue;
        dfs(v, u);
        dp[u][0] += dp[v][1];
        dp[u][1] += min(dp[v][0], dp[v][1]);
    }
}

int main() {
    int n;
    cin >> n;

    for (int i = 0; i < n; ++i) {
        int u, k;
        cin >> u >> k;
        for (int j = 0; j < k; ++j) {
            int v;
            cin >> v;
            tree[u].push_back(v);
            tree[v].push_back(u);
        }
    }

    dfs(0, -1);

    cout << min(dp[0][0], dp[0][1]) << endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值