社区讨论
95分,被卡长求调
P2680[NOIP 2015 提高组] 运输计划参与者 3已保存回复 3
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @mivicxia
- 此快照首次捕获于
- 2025/12/07 17:16 2 个月前
- 此快照最后确认于
- 2025/12/10 17:35 2 个月前
CPP
#include<bits/stdc++.h>
using namespace std;
const int N = 3*1e5+10;
vector<pair<int,int> > g[N];
inline int read()
{
int s=0,w=1;
char c=getchar();
while (!isdigit(c))
{
if (c=='-') w=-1;
c=getchar();
}
while (isdigit(c))
{
s=s*10+c-'0';
c=getchar();
}
return s*w;
}
int fa[N][20],deep[N];
int dist[N],path_len[N];
vector<pair<int,int> > ed;
int val[N],n,k,max_len;
void dfs(int u,int f,int w){
deep[u] = deep[f]+1;
dist[u] = dist[f]+w;
fa[u][0] = f;
for(int i = 1;i<20;i++) fa[u][i] = fa[fa[u][i-1]][i-1];
for(auto [v,we]:g[u]){
if(v==f) continue;
dfs(v,u,we);
}
}
int lca(int x,int y){
if(deep[x]<deep[y]) swap(x,y);//确保X的深度大于y
for(int i = 19;i>=0;i--){
if(deep[fa[x][i]]>=deep[y]){
x = fa[x][i];//保证深度相同
}
}
if(x==y) return x;//如果x和y相同,直接返回
//x,y深度相同,同时往上跳
for(int i = 19;i>=0;i--){
if(fa[x][i]!=fa[y][i]){
x = fa[x][i];
y = fa[y][i];
}
}
return fa[x][0];//!!!
}
void sum(int u,int f){
for(auto [v,we]:g[u]){
if(v==f) continue;
sum(v,u);
val[u]+=val[v];
}
}
bool check(int mid){
int cnt = 0;
max_len = 0;
memset(val,0,sizeof(val));
for(int i = 0;i<k;i++){
if(path_len[i]>mid){
cnt++;
max_len = max(max_len,path_len[i]);
auto [u,v] = ed[i];
int l = lca(u,v);
val[u]++;
val[v]++;
val[l]-=2;
}
}
sum(1,0);
for(int i = 2;i<=n;i++){
int tmp = dist[i]-dist[fa[i][0]];
if(val[i]==cnt && (max_len-tmp)<=mid) return 1;
}
return 0;
}
int main(){
n = read(),k = read();
for(int i = 1,x,y,w;i<n;i++){
x = read(),y = read(),w = read();
g[x].push_back({y,w});
g[y].push_back({x,w});
}
dfs(1,0,0);
max_len = 0;
for(int i = 0,u,v;i<k;i++){
u = read(),v = read();
ed.push_back({u,v});
path_len[i] = dist[u]+dist[v]-2*dist[lca(u,v)];
max_len = max(max_len,path_len[i]);
}
int l = -1,r = max_len+1;
while(l+1<r){
int mid = l+r>>1;
if(check(mid)) r = mid;
else l = mid;
}
cout<<r;
return 0;
}
回复
共 3 条回复,欢迎继续交流。
正在加载回复...