社区讨论
萌新求助QwQ,WAWAWA(只有50分)
P2680[NOIP 2015 提高组] 运输计划参与者 5已保存回复 12
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 12 条
- 当前快照
- 1 份
- 快照标识符
- @mi6umj93
- 此快照首次捕获于
- 2025/11/20 11:05 4 个月前
- 此快照最后确认于
- 2025/11/20 14:37 4 个月前
CPP
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<climits>
#include<cstring>
using namespace std;
int n,m,k=0,sum;
int e[600005],next[600005],last[300005],val[600005];
int u[300005],v[300005];
int f[300005][20],d[300005],dis[300005];
int cha[300005];
void Build_Edge(int x,int y,int z)
{
++k;
e[k]=y;
next[k]=last[x];
last[x]=k;
val[k]=z;
}
void Build_Tree(int x,int fa,int deepth)
{
f[x][0]=fa;
d[x]=deepth;
int u=last[x];
while(u>0)
{
int v=e[u];
if(v!=fa)
{
dis[v]=dis[x]+val[u];
Build_Tree(v,x,deepth+1);
}
u=next[u];
}
}
void Pre_LCA()
{
for(int i=1;i<=19;++i)
for(int j=1;j<=n;++j)
f[j][i]=f[f[j][i-1]][i-1];
}
int lca(int x,int y)
{
if(d[x]<d[y])
{
int q=x;
x=y;
y=q;
}
if(d[x]>d[y])
{
for(int i=19;i>=0;--i)
if(d[f[x][i]]>d[y]) x=f[x][i];
x=f[x][0];
}
if(x==y) return x;
for(int i=19;i>=0;--i)
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
return f[x][0];
}
struct plan{
int u,v,d;
}a[300005];
bool cmp(plan x,plan y)
{
return x.d>y.d;
}
int find(int x)
{
int l=0,r=m;
while(l<r)
{
int mid=(l+r+1)/2;
if(a[mid].d>x) l=mid;
else r=mid-1;
}
return r;
}
void dfs(int x)
{
int pp=0;
int u=last[x];
while(u>0)
{
int v=e[u];
if(v!=f[x][0])
{
dfs(v);
if(cha[v]==k) pp=max(pp,val[u]);
cha[x]+=cha[v];
}
u=next[u];
}
if(cha[x]==k) sum=max(pp,val[u]);
}
bool check(int ans)
{
k=find(ans);
memset(cha,0,sizeof(cha));
for(int i=1;i<=k;++i)
{
int x=a[i].u,y=a[i].v;
int p=lca(x,y);
--cha[f[p][0]];
++cha[x];
++cha[y];
--cha[p];
}
if(k==0) return true;
sum=0;
dfs(1);
if(a[1].d-sum>ans) return false;
else return true;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n-1;++i)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
Build_Edge(x,y,z);
Build_Edge(y,x,z);
}
Build_Tree(1,0,1);
Pre_LCA();
for(int i=1;i<=m;++i)
{
int x,y;
scanf("%d%d",&x,&y);
a[i].u=x;
a[i].v=y;
int p=lca(x,y);
a[i].d=dis[x]+dis[y]-2*dis[p];
}
sort(a+1,a+m+1,cmp);
int l=0,r=INT_MAX/3;
while(l<r)
{
int mid=(l+r)/2;
if(check(mid)) r=mid;
else l=mid+1;
}
printf("%d",r);
return 0;
}
回复
共 12 条回复,欢迎继续交流。
正在加载回复...