首页 > 其他分享 >[题解]P1967 [NOIP2013 提高组] 货车运输

[题解]P1967 [NOIP2013 提高组] 货车运输

时间:2024-06-09 15:54:54浏览次数:17  
标签:minn int 题解 货车运输 fa edges ans P1967 ffa

P1967 [NOIP2013 提高组] 货车运输

题意简述

给定一个\(N\)个节点,\(M\)条边的无向图,其中每条边有一个边权。

接下来给定\(q\)次询问。每次询问给出\(x,y\),请计算\(x\)到\(y\)路径上最小边权的最大值是多少。

解题思路

我们对于每个连通块跑一遍最大生成树。这样整张图就成了一片森林。

接下来对于森林里的每一棵树,跑一遍LCA,顺便维护\(minn[pos][n]\)表示\(pos\)向上\(2^n\)层的最小边权。查询时,每跳一步更新最小边权,最终返回最小边权即可。

时间复杂度\(O(m\log m+q\log n)\)。

点击查看代码
#include<bits/stdc++.h>
#define N 10010
#define M 50010
using namespace std;
int n,m,q,ffa[N],dep[N],fa[N][20],minn[N][20];
//ffa用于并查集,fa用于LCA
bool vis[N];
struct tedge{int u,v,w;}edges[M];
bool cmp(tedge a,tedge b){return a.w>b.w;}
int find(int x){
	if(ffa[x]==x) return x;
	return ffa[x]=find(ffa[x]);
}
struct edge{int to,w;};
vector<edge> G[N];
void dfs(int u,int father){
	vis[u]=1;
	dep[u]=dep[father]+1;
	fa[u][0]=father;
	for(int i=1;i<20;i++)
		fa[u][i]=fa[fa[u][i-1]][i-1],
		minn[u][i]=min(minn[u][i-1],minn[fa[u][i-1]][i-1]);
	for(auto i:G[u])
		if(i.to!=father){
			minn[i.to][0]=i.w;
			dfs(i.to,u);
		}
}
int lca(int u,int v){
	if(dep[u]<dep[v]) swap(u,v);
	int ans=INT_MAX;
	for(int i=19;i>=0;i--)
		if(dep[fa[u][i]]>=dep[v])
			ans=min(ans,minn[u][i]),
			u=fa[u][i];
	if(u==v) return ans;
	for(int i=19;i>=0;i--)
		if(fa[u][i]!=fa[v][i])
			ans=min(ans,min(minn[u][i],minn[v][i])),
			u=fa[u][i],v=fa[v][i];
	ans=min(ans,min(minn[u][0],minn[v][0]));
	return ans;
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++) ffa[i]=i;
	for(int i=1;i<=m;i++)
		cin>>edges[i].u>>edges[i].v>>edges[i].w;
	sort(edges+1,edges+1+m,cmp);
	for(int i=1;i<=m;i++){
		int u=find(edges[i].u),v=find(edges[i].v);
		if(u==v) continue;
		ffa[u]=v;
		G[edges[i].u].push_back({edges[i].v,edges[i].w});
		G[edges[i].v].push_back({edges[i].u,edges[i].w});
	}
	for(int i=1;i<=n;i++) if(!vis[i]) dfs(i,0);
	cin>>q;
	while(q--){
		int x,y;
		cin>>x>>y;
		if(find(x)!=find(y)) cout<<"-1\n";
		else cout<<lca(x,y)<<"\n";
	}
	return 0;
}

标签:minn,int,题解,货车运输,fa,edges,ans,P1967,ffa
From: https://www.cnblogs.com/Sinktank/p/18239566

相关文章

  • 2024年新高考1卷精选试题解答
    **(2024年新高考1卷18题)**已知函数$f(x)=\ln\fracx{2-x}+ax+b(x-1)^{3}$.(1)若$b=0$,且$f'(x)\geqslant0$,求$a$的最小值;(2)证明:曲线$y=f(x)$是中心对称图形;(3)若$f(x)>-2$当且仅当$1<x<2$,求$b$的取值范围.**解.**函数$f(x)$的定义域为$(0,2)$.(1)若$b=0$,则$f\left......
  • 题解集合
    黑暗爆炸(BZOJ)3196洛谷P3380AtCoderabc340_fabc345_fabc346_aabc346_babc346_cabc346_dabc346_eabc350_fabc350_gabc351_dabc351_fLibreOJ106......
  • [题解]P3398 仓鼠找 sugar
    P3398仓鼠找sugar题意简述给定一个\(N\)个节点的树形结构。接下来有\(q\)次询问,每次询问给定\(4\)个节点\(a,b,c,d\),请计算\(a\)到\(b\)的简单路径和\(c\)到\(d\)的简单路径是否有相交的节点。对于每个询问,输出Y/N表示答案。解题思路&Code通过手玩样例可以发现,\(a\simb\)......
  • 【题解】[CSP-J 2019] 公交换乘
    题目描述题目大意给出\(n\)次出行记录(地铁或公交车),有以下优惠方案:搭乘一次地铁后可以获得一张有效期为45分钟的优惠票,可以免费搭乘一次票价不超过该地铁票价的公交车。优惠票可以累计存储优先使用过期时间早的优惠票。思路枚举每一次出行:如果是地铁。累加花费,并记......
  • [题解]P6374 「StOI-1」树上询问
    题意简述给定一个\(N\)个节点的树,接下来有\(q\)次询问。每次询问给定\(a,b,c\),请问存在多少个节点\(i\),使得这棵树在以\(i\)为根的情况下,\(a\)和\(b\)的LCA是\(c\)。解题思路首先通过分析样例,我们发现:\(a,b\)的LCA一定在它们之间的简单路径上,所以如果\(c\)不在\(a,b\)之间的简......
  • CF1552G A Serious Referee 题解
    题目链接点击打开链接题目解法感觉很神奇的题首先把序列当成排列做首先发现只要当成\(01\)序列做就是对的为什么?你假设有数\(x<y\),你把\(\lex\)的数设成\(0\),\(>x\)且\(\ley\)的数设成\(1\),\(>y\)的数设成\(2\),然后做题目中的排序操作,如果最终序列形成逆序......
  • CF717G Underfail 题解
    题意:若干区间,区间有权值,选择一个子集,使得权值和尽量大并且每个点不被覆盖超过\(x\)次。\(n\le500\)思路:很神奇的一道题。我们考虑费用流,如果单纯的一边是区间一边是点的话其实并不好做,所以这道题我们直接建一排\(n+2\)个点,一个区间\(l,r\)就从\(l\)到\(r+1\)连......
  • CCF-GESP 等级考试 2023年9月认证C++四级真题解析
    一、单选题(每题2分,共30分)第1题⼈们所使⽤的⼿机上安装的App通常指的是()。A.⼀款操作系统B.⼀款应⽤软件C.⼀种通话设备D.以上都不对正确答案:B.⼀款应⽤软件解析:App是"Application"的缩写,中文意思是"应用",特指安装在智能手机上的第三方应用软件。这些软件通常......
  • 打砖块 题解
    题目链接\(50pts\)对于没有\(Y\)砖的情况,可以用分组背包解决,算出每一列打\(j\)块砖需要的子弹以及对分数的贡献,按照分组背包即可。对于包含\(Y\)砖的情况,不能直接分组背包解决。这实际上是打的顺序问题,比如:NYNY如果手上有两枚子弹,最优策略是先打掉第二列,再打掉第......
  • 【Selenium+java环境配置】(超详细教程常见问题解决)
    Selenium+java环境配置windows电脑环境搭建-chrome浏览器1.下载chrome浏览器2.查看chrome浏览器版本3.下载chrome浏览器驱动4.配置系统环境变量PATH验证环境是否搭建成功1.创建java项目,添加pom文件中添加依赖2.编写代码运行常见问题&解决办法1.访问失败Theversio......