This commit is contained in:
Zengtudor 2024-11-19 09:10:15 +08:00
parent 195b2065c5
commit 0ddc2570ac
3 changed files with 98 additions and 34 deletions

View File

@ -1,52 +1,26 @@
#include <algorithm>
#include <cstdint>
#include <iostream>
#include <map>
#include <utility>
#include <vector>
using ll = int64_t;
using std::cin, std::cout;
const ll maxn=5e5+5, inf{1l<<(sizeof(inf)*8-4)};
ll n, k, kd[maxn], mkd[maxn];
const ll maxn = 5e5+5;
ll n, k, a[maxn];
std::vector<std::pair<ll, ll>> adj[maxn];
int main(){
std::iostream::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
cin>>n>>k;
std::fill(mkd, mkd+1+k, -inf);
std::vector<std::vector<ll>> adj(n+1, std::vector<ll>(n+1,inf));
for(ll i{1};i<=n;i++){
cin>>kd[i];
}
for(ll i{1};i<=n;i++)cin>>a[i];
for(ll i{1};i<n;i++){
ll u,v,w;
cin>>u>>v>>w;
adj[u][v]=adj[v][u]=std::min({
adj[u][v],
adj[v][u],
w
});
}
for(ll k{1};k<=n;k++){
for(ll i{1};i<=n;i++){
for(ll j{1};j<=n;j++){
adj[i][j]=std::min(
adj[i][j],
adj[i][k]+adj[k][j]
);
}
}
}
for(ll i{1};i<=n;i++){
for(ll j{1};j<=n;j++){
if(i!=j && kd[i]==kd[j]){
mkd[kd[i]]=std::max(mkd[kd[i]], adj[i][j]);
}
}
}
for(ll i{1};i<=k;i++){
cout<<(mkd[i]==inf?-1:mkd[i])<<'\n';
adj[u].emplace_back(v,w);
adj[v].emplace_back(u,w);
}
}

38
src/20241118/T541156.md Normal file
View File

@ -0,0 +1,38 @@
这段代码中的 `if` 语句主要是用于确保在更新暴龙的红温值 (最大距离) 时判断当前的节点类型与子树中的节点类型之间的关系。具体来说,这里是在处理当前节点 `u` 和子节点 `v` 之间的距离关系,同时考虑了他们的暴龙类型。
我们来逐步解析这个 `if` 语句及其包含的逻辑:
```cpp
if((a[u] == kk || dp[u][kk] > 0) && (a[v] == kk || dp[v][kk] > 0)) {
ans[kk] = max(ans[kk], dp[u][kk] + dp[v][kk] + w);
}
```
### 变量说明
- `kk`: 表示当前正在处理的暴龙类型的标识符(通常是种类编号)。
- `a[u]`: 当前节点 `u` 的暴龙类型。
- `dp[u][kk]`: 从当前节点 `u` 开始的子树中,该暴龙类型 `kk` 的最大距离。
- `dp[v][kk]`: 从子节点 `v` 开始的子树中,该暴龙类型 `kk` 的最大距离。
- `w`: 当前节点 `u` 和子节点 `v` 之间的边的权重(即两者之间的距离)。
- `ans[kk]`: 用于存储当前暴龙类型 `kk` 的红温值(最大距离)。
### 逻辑解释
1. **类型匹配**:
- `(a[u] == kk || dp[u][kk] > 0)`:
- 这个条件检查当前节点 `u` 是否是类型 `kk` 或者在 `u` 的子树中已经存在类型 `kk` 的暴龙。如果存在,可以考虑将 `u``v` 之间的距离计算入 `ans[kk]`
- `(a[v] == kk || dp[v][kk] > 0)`:
- 这个条件检查子节点 `v` 是否是类型 `kk` 或者在 `v` 的子树中已经存在类型 `kk` 的暴龙。类似地,如果存在,也可以考虑将 `u``v` 之间的距离计算入 `ans[kk]`
2. **计算距离**:
- 如果以上两个条件都是满足的,表示 `u``v` 之间的边可以被计算在类型 `kk` 的红温值中,因此最大距离被更新为:
```cpp
ans[kk] = max(ans[kk], dp[u][kk] + dp[v][kk] + w);
```
- 这里的 `dp[u][kk] + dp[v][kk] + w` 即为通过当前边 `u-v` 连接的所有类型为 `kk` 的暴龙之间的距离。
### 总结
这个 `if` 判断的作用在于决定是否可以将当前边 `u-v` 的权重 `w` 加入到 `ans[kk]` 中,从而更新当前暴龙类型 `kk` 的最大红温值。这确保了只有在当前节点及其子节点之间具有相同暴龙类型时,才会合并和计算它们之间的边的影响。这样能够更精确地得到不同类型暴龙之间的距离关系。

View File

@ -0,0 +1,52 @@
#include <algorithm>
#include <cstdint>
#include <iostream>
#include <map>
#include <utility>
#include <vector>
using ll = int64_t;
using std::cin, std::cout;
const ll maxn=5e5+5, inf{1l<<(sizeof(inf)*8-4)};
ll n, k, kd[maxn], mkd[maxn];
int main(){
std::iostream::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
cin>>n>>k;
std::fill(mkd, mkd+1+k, -inf);
std::vector<std::vector<ll>> adj(n+1, std::vector<ll>(n+1,inf));
for(ll i{1};i<=n;i++){
cin>>kd[i];
}
for(ll i{1};i<n;i++){
ll u,v,w;
cin>>u>>v>>w;
adj[u][v]=adj[v][u]=std::min({
adj[u][v],
adj[v][u],
w
});
}
for(ll k{1};k<=n;k++){
for(ll i{1};i<=n;i++){
for(ll j{1};j<=n;j++){
adj[i][j]=std::min(
adj[i][j],
adj[i][k]+adj[k][j]
);
}
}
}
for(ll i{1};i<=n;i++){
for(ll j{1};j<=n;j++){
if(i!=j && kd[i]==kd[j]){
mkd[kd[i]]=std::max(mkd[kd[i]], adj[i][j]);
}
}
}
for(ll i{1};i<=k;i++){
cout<<(mkd[i]==inf?-1:mkd[i])<<'\n';
}
}