先贴个题目:
以及题目链接:1207. 大臣的旅费 - AcWing题库https://www.acwing.com/problem/content/1209/
讲讲思路,emmmm第一次做和图相关的题,差点把脑子烧坏了,这题涉及的知识点包括bfs(或dfs)和树的直径。由题意,我们可以发现除了首都(根节点)其他节点都是出度和入度都为1的节点,并且每个节点和首都(根节点)有且仅有一条路径,所以求最大花费就是求两个节点间的最大距离,也被叫做树的直径。那么怎么求出这个直径所在的两个点呢?我使用的一个方式是从首都(可以从任意节点)为起点开始搜索,搜索到的最远节点必然是直径所在的两个点的其中之一,然后再对这个节点进行搜素,搜到的最远点就是直径的另一个节点。那怎么证明这个方法的正确性呢,我们不妨画个图讨论下。
我们假设UV为直径,X点是搜索起点,Y为搜索到的最远点。
先说第一种情况:直径UV和XY有交点:那么就会有
由于UV为直径,所以VY必然是直径。所以Y必然是直径上一点。
再看第二种情况:直径XY和UV没交点,那根据定义,必然可以在这两个线段中找到两点相连,如图。那么就会有
由于UV为直径,所以UY必然是直径,所以Y必然是直径上一点。
由此,我们证明了这个理论的正确性,就可以做这题了。
还有一个知识点就是有关建图,我暂时只学了vector建图(逃)就是开N(节点数)个动态数组,然后数组内部是一个结构体
struct road
{
int id, w;
};
如图:id存的是当先节点(下标表示)和id这个节点有通路,边权为w。
具体的来看看代码,我写了dfs和bfs两版,可供参考。
dfs:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 1e6;
int n;
struct road
{
int id;
int w;
};
vector<road> map[N];
int dis[N];
void dfs(int x, int father, int distance)
{
dis[x] = distance;
for (int i = 0; i < map[x].size(); ++i)
{
if (father != map[x][i].id)
dfs(map[x][i].id, x, distance + map[x][i].w);
}
return;
}
int main()
{
cin >> n;
int x, y, w;
for (int i = 0; i < n - 1; ++i)
{
scanf("%d%d%d", &x, &y, &w);
map[x].push_back({y, w});
map[y].push_back({x, w});
}
dfs(1, -1, 0);
int d1 = 1, Maxd = dis[1];
for (int i = 1; i < n + 1; ++i)
if (dis[i] > Maxd)
{
Maxd = dis[i];
d1 = i;
}
dfs(d1, -1, 0);
for (int i = 1; i < n + 1; ++i)
if (dis[i] > Maxd)
{
d1 = i;
Maxd = dis[i];
}
ll sum = Maxd * 10 + (long long)(1 + Maxd) * Maxd / 2;
printf("%lld", sum);
return 0;
}
bfs:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 1e6;
struct road
{
int id, w;
};
vector<road> map[N];
int dist[N];
bool sign[N];
void bfs(int x)
{
queue<int> q;
q.push(x);
sign[x] = true;
dist[x] = 0;
while (q.size())
{
int id = q.front();
q.pop();
for (int i = 0; i < map[id].size(); ++i)
if (!sign[map[id][i].id])
{
sign[map[id][i].id] = true;
dist[map[id][i].id] = dist[id] + map[id][i].w;
q.push(map[id][i].id);
}
}
return;
}
int main()
{
int n;
cin >> n;
int x, y, w;
for (int i = 1; i < n; ++i)
{
scanf("%d%d%d", &x, &y, &w);
map[x].push_back({y, w});
map[y].push_back({x, w});
}
bfs(1);
int d1 = 1, Maxd = dist[1];
for (int i = 1; i < n + 1; ++i)
{
if (dist[i] > Maxd)
{
Maxd = dist[i];
d1 = i;
}
}
memset(sign, 0, sizeof(sign));
bfs(d1);
Maxd = dist[1];
for (int i = 1; i < n + 1; ++i)
{
if (dist[i] > Maxd)
{
Maxd = dist[i];
d1 = i;
}
}
ll sum = Maxd * 10 + (ll)(Maxd + 1) * Maxd / 2;
cout << sum;
return 0;
}
后面想到啥再补充吧。
by————2024.4.9刷题记录