本题思路来源:AC大佬代码。
思路:
枚举中转点,那么最长的路就是以中转点为起点的最短路中最长的两条的和。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
typedef pair<int, int> pii;
const int mod = 1e4;
const int N = 1009;
int n, m;
int head[N], to[2 * N], wi[2 * N], nex[2 * N], tot;
void add(int x, int y, int w) {
tot ++; nex[tot] = head[x]; head[x] = tot; /// 下标从 1 开始。
to[tot] = y; wi[tot] = w;
}
priority_queue<pii> pq;
int vis[N], cost[N];
int dij(int h) {
memset(vis, 0, sizeof(vis));
memset(cost, 0x3f, sizeof(cost));
cost[h] = 0;
pq.push({0, h});
int max1 = 0, max2 = 0, x;
while(!pq.empty()){
x = pq.top().second; pq.pop();
if(vis[x] ++) continue;
max2 = max(max2, cost[x]);
if(max1 < max2) swap(max1, max2);
for(int i = head[x], p; i; i = nex[i]) {
p = to[i];
if(vis[p] || wi[i] + cost[x] >= cost[p]) continue;
cost[p] = cost[x] + wi[i];
pq.push({-cost[p], p}); /// 用大根堆,故存储相反数
}
}
if(max2 == 0) return -1; /// 找不到两个长度不为零的点
return max1 + max2;
}
int main(){
int t; cin >> t;
while(t --) {
memset(head, 0, sizeof(head)); tot = 0;
cin >> n >> m;
int x, y, w;
for(int i = 0; i < m; i ++) {
cin >> x >> y >> w;
add(x, y, w); add(y, x, w);
}
int ans = -1;
for(int i = 1; i <= n; i ++) { /// 枚举中转点
ans = max(ans, dij(i));
}
cout << ans << endl;
}
return 0;
}

京公网安备 11010502036488号