社区讨论

萌新求助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 条回复,欢迎继续交流。

正在加载回复...