社区讨论

求助,5pts

P2680[NOIP 2015 提高组] 运输计划参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@lo2rsn2d
此快照首次捕获于
2023/10/23 18:44
2 年前
此快照最后确认于
2023/10/23 18:44
2 年前
查看原帖
只有5分,按照这篇题解改了半天还是5分,还多改出来一个RE
C
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3e5+5;
inline int read(){
	int x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=(x<<3)+(x<<1)+c-48;
		c=getchar();
	}
	return x*f;
}
struct node{
	int to,next,w;
}edge[N<<1];
struct no{
	int u,v,lcaa,diss;
}l[N<<1];

int n,m,summ,cnt,num[N],vis[N];
int temp[N],deep[N],dis[N];
int fa[N][25],dp[N][25];
int tot,head[N];
inline void add_edge(int u,int v,int w){
	tot++;
	edge[tot].to=v;
	edge[tot].next=head[u];
	edge[tot].w=w;
	head[tot]=tot;
}

inline void dfs(int x,int pa,int dep){
	cnt++;
	num[cnt]=x;
	deep[x]=dep;
	vis[x]=1;
	for(int i=1;i<25;i++)
		fa[x][i]=fa[fa[x][i-1]][i-1];
	for(int i=head[x];i>0;i=edge[i].next){
		int v=edge[i].to;
		if(!vis[v]){
			fa[v][0]=x;
			dis[v]=dis[x]+edge[i].w;
			dfs(v,x,dep+1);
		}
	}
}

inline int lca(int x,int y){
	if(deep[x]<deep[y]) swap(x,y);
	int t=deep[x]-deep[y];
	for(int i=0;i<25;i++)
		if((1<<i)&t) x=fa[x][i];
	if(x==y)return x;
	for(int i=24;i>=0;i--)
		if(fa[x][i]!=fa[y][i]){
			x=fa[x][i];
			y=fa[y][i];
		}
	return fa[x][0];
}

inline bool check(int mid){
	int cnt=0,ans=0;
	memset(temp,0,sizeof temp);
	for(int i=1;i<=m;i++){
		if(l[i].diss>mid){
			temp[l[i].u]++;temp[l[i].v]++;temp[l[i].lcaa]-=2;
			ans=max(ans,l[i].diss-mid);
			cnt++;
		}
	}
	if(cnt==0)return 1;
	for(int i=n;i>=1;i--)temp[fa[num[i]][0]]+=temp[num[i]];
	for(int i=2;i<=n;i++)if(temp[i]==cnt&&dis[i]-dis[fa[i][0]]>=ans)return 1;
	return 0;
}

int main(){
	n=read(),m=read();
	for(int i=1;i<n;i++){
		int x=read(),y=read(),w=read();
		add_edge(x,y,w);add_edge(y,x,w);
		summ+=w;
	}
	dis[1]=0;
	dfs(1,0,1);
	for(int i=1;i<=m;i++){
		l[i].u=read(),l[i].v=read();
		l[i].lcaa=lca(l[i].u,l[i].v);
		l[i].diss=dis[l[i].u]+dis[l[i].v]-2*dis[l[i].lcaa];
	}
	int l=0,r=summ;
	while(l<r){
		int mid=(l+r)>>1;
		if(check(mid))r=mid;
		else l=mid+1;
	}
	printf("%d",l);
	return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...