第一题构造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;
}