ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P1967 [NOIP2013 提高组] 货车运输

2022-04-22 16:01:58  阅读:140  来源: 互联网

标签:dad NOIP2013 edg minn int res 货车运输 maxn P1967


首先能想到floyed暴力做法 60分是没问题的

进一步 两点之间路径可能会有多条 但是我们只用找到路径上最长边最小的那条

但是因为有多个询问 所以我们不能单方面考虑两个点 而是考虑很多对两个点

考虑建立最大生成树 这样的解一定是最优的!!!很巧妙

最后找两点之间的最短的那条边 用倍增lca 顺便维护最短边就好

注意可能最后建的图可能是个森林!!!

这个题综合性很强 是一道非常不错的题目

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
#define inf 2e9+7
const int maxn=1e4+5;
int n,m,cnt,T;
int head[maxn],fa[maxn],dp[maxn],dad[maxn][21],minn[maxn][21],vis[maxn];
int find(int x){
	if(x!=fa[x])return fa[x]=find(fa[x]);
	return x;
}
struct node{
	int to,next,w,u;
}ed[maxn*5],edg[maxn*5];
bool cmp(node a,node b){
	return a.w>b.w;
}
void add(int u,int v,int w){
	edg[++cnt].next=head[u];head[u]=cnt;edg[cnt].to=v;edg[cnt].w=w;edg[cnt].u=u;
}
void dfs(int,int);
void lca(int,int);
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)fa[i]=i;
	for(int i=1;i<=m;i++){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		ed[i].to=y;ed[i].u=x;ed[i].w=z;
	}
	sort(ed+1,ed+1+m,cmp);
	for(int i=1;i<=m;i++){
		int u=ed[i].u,v=ed[i].to,w=ed[i].w;
		int fu=find(u),fv=find(v);
		if(fu!=fv){
			add(u,v,w);
			add(v,u,w);
			fa[fv]=fu;
		}
	}
	for(int i=1;i<=n;i++)
	if(!vis[i]){
		dp[i]=1;
		dad[i][0]=i;
		minn[i][0]=inf;
		dfs(i,i);
	}
	for(int j=1;j<21;j++)
	for(int i=1;i<=n;i++)
	dad[i][j]=dad[dad[i][j-1]][j-1],minn[i][j]=min(minn[i][j-1],minn[dad[i][j-1]][j-1]);
	cin>>T;
	while(T--){
		int x,y;
		scanf("%d%d",&x,&y);
		lca(x,y);
	}
     return 0;
}
void dfs(int u,int f){
	vis[u]=1;
	for(int i=head[u];i;i=edg[i].next){
		int to=edg[i].to;
		if(to==f)continue;
		dad[to][0]=u;
		minn[to][0]=edg[i].w;
		dp[to]=dp[u]+1;
		dfs(to,u);
	}
}
void lca(int a,int b){
	if(find(a)!=find(b)){
		cout<<"-1"<<endl;
		return;
	}
	if(dp[a]<dp[b])swap(a,b);
	int res=inf;
	for(int i=20;i>=0;i--)
	if(dp[dad[a][i]]>=dp[b])res=min(res,minn[a][i]),a=dad[a][i];//一定要先跟新res再向上跳
	if(a==b){
		cout<<res<<endl;
		return;
	}
	for(int i=20;i>=0;i--)
	if(dad[a][i]!=dad[b][i]){
		res=min(res,minn[a][i]);
		res=min(res,minn[b][i]);
		a=dad[a][i];b=dad[b][i];
	}
	res=min(res,minn[a][0]);
	res=min(res,minn[b][0]);
	cout<<res<<endl;
}

标签:dad,NOIP2013,edg,minn,int,res,货车运输,maxn,P1967
来源: https://www.cnblogs.com/wzxbeliever/p/16179220.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有