1207-大臣的旅费
题目描述
关系
内容
很久以前,
为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。
为节省经费,
同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。
所以,从一个城市马不停蹄地到另一个城市成了
他有一个钱袋,用于存放往来城市间的路费。
聪明的
具体来说,一段连续的旅途里,第
也就是说,如果一段旅途的总长度为
输入格式
输入的第一行包含一个整数
城市从
接下来
每行三个整数
输出格式
输出一个整数,表示大臣
数据范围
输入样例:
5
1 2 2
1 3 1
2 4 5
2 5 4
输出样例:
135
问题分析
最初思路
暴力的方式是,遍历每一个节点,以每一个节点为 bfs 的开头,查找最远距离,最后得出答案。但是,这是超时的。
矛盾是没有固定一个起始位置。
有两种情况,一种是不经过首都,一种是经过首都的路径。麻烦的是后者,如果能够维护一个二维数组,用来记录每个节点到首都的距离,那么后者就解决了。
思路分析
这道题是树的直径,001-1072-树的最长路径。
执行流程设计
总结
代码实现
bfs
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct edge {
int id, w;
};
const int N = 1e5 + 10;
int n;
vector<edge> h[N];
int dis[N];
bool st[N];
void bfs(int u) {
queue<int> q;
q.push(u);
st[u] = true;
dis[u] = 0;
while (!q.empty()) {
int c = q.front();
q.pop();
for (auto e: h[c]) {
if (st[e.id]) continue;
st[e.id] = true;
dis[e.id] = dis[c] + e.w;
q.push(e.id);
}
}
}
int main()
{
cin >> n;
for (int i = 0; i < n - 1; i++) {
int a, b, c;
cin >> a >> b >> c;
h[a].push_back({b, c});
h[b].push_back({a, c});
}
bfs(1);
int m = 1;
for (int i = 1; i <= n; i++)
if (dis[i] > dis[m]) m = i;
memset(st, 0, sizeof st);
bfs(m);
for (int i = 1; i <= n; i++)
if (dis[i] > dis[m]) m = i;
ll s = dis[m];
ll ans = (21 + s) * s / 2;
printf("%lld", ans);
return 0;
}
dfs
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct edge {
int id, w;
};
const int N = 1e5 + 10;
int n;
vector<edge> h[N];
int dis[N];
void dfs(int u, int father, int distance) {
dis[u] = distance;
for (auto e: h[u]) {
if (e.id != father) {
dfs(e.id, u, e.w + distance);
}
}
}
int main()
{
cin >> n;
for (int i = 0; i < n - 1; i++) {
int a, b, c;
cin >> a >> b >> c;
h[a].push_back({b, c});
h[b].push_back({a, c});
}
dfs(1, -1, 0);
int m = 1;
for (int i = 1; i <= n; i++)
if (dis[i] > dis[m]) m = i;
dfs(m, -1, 0);
for (int i = 1; i <= n; i++)
if (dis[i] > dis[m]) m = i;
ll s = dis[m];
ll ans = (21 + s) * s / 2;
printf("%lld", ans);
return 0;
}