首页 > 其他分享 >UVA12655 Trucks 题解

UVA12655 Trucks 题解

时间:2023-10-01 13:56:24浏览次数:42  
标签:cnt Trucks fa int 题解 memset 700001 UVA12655 fminn

题目传送门

前言

中文题目可以看 link

前置知识

Kruskal 重构树 | 最近公共祖先

简化题意

给定一个 \(N\) 个点 \(M\) 条边的有向图,共有 \(S\) 次询问,每次询问从 \(L\) 到 \(H\) 所有的路径中最小的权值的最大值(多组数据)。

  • 本题即最大瓶颈路问题。

解法

使最小的权值最大,不难想到利用 Kruskal 重构树算法求解。

  • 最小的权值最大的这个权值一定出现在原图的最大生成树上。

令 \(rt\) 表示原图的最大生成树的树根,\(dis_{i,j}\) 表示从 \(i\) 到 \(j\) 的路径上的最小值,不难得出 \(dis_{i,j}=\min(dis_{i,lca_(i,j)},dis_{j,lca(i,j)})\)。求任意两点的 LCA 可以用倍增或树剖等做法,此题使用倍增做法。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define sort stable_sort 
#define endl '\n'
struct node
{
	int nxt,from,to,w;
}e[700001],E[700001];
int head[700001],dep[700001],fminn[700001][25],fa[700001][25],f[700001],N,cnt=0;
bool cmp(node a,node b)
{
	return a.w>b.w;
}
void add(int u,int v,int w)
{
	cnt++;
	e[cnt].nxt=head[u];
	e[cnt].to=v;
	e[cnt].w=w;
	head[u]=cnt;
}
int find(int x)
{
	if(f[x]==x)
	{
		return x;
	}
	else
	{
		return f[x]=find(f[x]);
	}
}
void kruskal(int m)
{
	int i,x,y;
	sort(E+1,E+1+m,cmp);
	for(i=1;i<=m;i++)
	{
		x=find(E[i].from);
		y=find(E[i].to);
		if(x!=y)
		{
			f[x]=y;
			add(E[i].from,E[i].to,E[i].w);
			add(E[i].to,E[i].from,E[i].w);
		}
	}
}
void dfs(int x,int father,int w)
{
	fa[x][0]=father;
	dep[x]=dep[father]+1;
	fminn[x][0]=w;
	for(int i=1;(1<<i)<=dep[x];i++)
	{
		fa[x][i]=fa[fa[x][i-1]][i-1];
		fminn[x][i]=min(fminn[x][i-1],fminn[fa[x][i-1]][i-1]);
	}
	for(int i=head[x];i!=0;i=e[i].nxt)
	{
		if(e[i].to!=father)
		{
			dfs(e[i].to,x,e[i].w);
		}
	}
}
int lca(int x,int y)
{
	if(find(x)!=find(y))
	{
		return -1;
	}
	else
	{
		int minn=0x7f7f7f7f;
		if(dep[x]>dep[y])
		{
			swap(x,y);
		}
		for(int i=N;i>=0;i--)
		{
			if(dep[x]+(1<<i)<=dep[y])
			{
				minn=min(minn,fminn[y][i]);
				y=fa[y][i];
			}
		}
		if(x==y)
		{
			return minn;
		}
		else
		{
			for(int i=N;i>=0;i--)
			{
				if(fa[x][i]!=fa[y][i])
				{
					minn=min(minn,min(fminn[x][i],fminn[y][i]));
					x=fa[x][i];
					y=fa[y][i];
				}
			}
			minn=min(minn,min(fminn[x][0],fminn[y][0]));
			return minn;
		}
	}
	
}
int main()
{
	int n,m,k,i,u,v,w,l,r;
	while(cin>>n>>m>>k)
	{
		cnt=0;
		memset(e,0,sizeof(e));
		memset(E,0,sizeof(E));
		memset(fa,0,sizeof(fa));
		memset(dep,0,sizeof(dep));
		memset(head,0,sizeof(head));
		memset(fminn,0x3f,sizeof(fminn));
		for(i=1;i<=n;i++)
		{
			f[i]=i;
		}
		for(i=1;i<=m;i++)
		{
			cin>>E[i].from>>E[i].to>>E[i].w;
		}
		kruskal(m);
		N=log2(n)+1;
		for(i=1;i<=n;i++)
		{
			if(dep[i]==0)
			{
				dfs(i,0,0x7f7f7f7f);
			}
		}
		for(i=1;i<=k;i++)
		{
			cin>>l>>r;
			cout<<lca(l,r)<<endl;
		}
	}
	return 0;
}

后记

多倍经验:P1967 | P9235 | UVA12655 | P2245 |UVA11354 | AT_joisc2014_e

标签:cnt,Trucks,fa,int,题解,memset,700001,UVA12655,fminn
From: https://www.cnblogs.com/The-Shadow-Dragon/p/17738796.html

相关文章

  • 【洛谷 P1305】新二叉树 题解(结构体数组+先序遍历+二叉树)
    新二叉树题目描述输入一串二叉树,输出其前序遍历。输入格式第一行为二叉树的节点数。()后面行,每一个字母为节点,后两个字母分别为其左右儿子。特别地,数据保证第一行读入的节点必为根节点。空节点用*表示输出格式二叉树的前序遍历。样例#1样例输入#16abcbdicj*d**i**j**......
  • SP16113 SUBTLEBA - Trucks Transportation 题解
    题目传送门前言本题样例有问题,如果想要样例可以去vjudge上。本题提交后可能会出现UKE,建议前往link提交,而且本篇题解中所提供的代码也为link代码。前置知识Kruskal重构树|最近公共祖先简化题意给定一个\(N\)个点\(M\)条边的有向图,共有\(S\)次询问,每次询问......
  • 题解 CF1875D【Jellyfish and Mex】
    显然,除非\(\operatorname{mex}a=0\),否则不会删除\(>\operatorname{mex}a\)的数。而\(\operatorname{mex}a=0\)时不对答案产生贡献,因此任意时刻我们都可以忽略\(a\)中\(>\operatorname{mex}a\)的数。又显然,一旦我们开始删一个数,就会先把所有与之相等的数删光。否则,设最先......
  • counting题解
    \(N,M\le1e7\)接着反射容斥,考虑这道题怎么做如果去枚举不动步数,加上反射容斥,直接T飞了把-1/0/1操作转换一下,就成了0/1/2如果没有限制(不能<0或>m),n步方案就是\((1+x+x^2)^n\)设\(H=1+x+x^2\quadF=H^n\)那么对两边求导:\[nH^{n-1}H'=F'\]\[F'H=nFH'\]我们知道\[H=1+x+x^2......
  • 第四周题解
    第四周题解7-1根据后续和中序遍历输出先序遍历利用数组保存树的后序遍历和中序遍历,根据后续遍历和中序遍历的特点还原树,并根据先序遍历的顺序,即根左右,利用函数递归输出打印,注意输出格式的正确性。#include<bits/stdc++.h>usingnamespacestd;constintN=40;typedeflon......
  • vs code调试rust乱码问题解决方案
    在terminal中用chcp65001修改一下字符集,就行了。有的博主推荐修改区域中的设置,这会引来很大的问题。千万不要修改如下设置:......
  • P7167 [eJOI2020 Day1] Fountain 题解
    Description给定\(n\)个从上往下圆心重叠的圆盘,给定每个圆盘的直径\(d_i\)和容量\(c_i\),所有圆盘底下有一个容量为\(\infty\)的水池,编号为\(0\)。\(q\)次询问,每次给定\(r\)和\(v\)表示往第\(r\)个圆盘里倒\(v\)的水,输出水最后流到哪个圆盘会停止。Solution倍......
  • 【题解】CF1110D Jongmah(DP)
    【题解】CF1110DJongmah代码很短,但是思路我怎么也想不到的神仙DP。题意概述你在玩一个叫做Jongmah的游戏,你手上有\(n\)个麻将,每个麻将上有一个在\(1\)到\(m\)范围内的整数\(a_i\)。为了赢得游戏,你需要将这些麻将排列成一些三元组,每个三元组中的元素是相同的或者连......
  • 洛谷题解 | AT_abc321_c Primes on Interval
    目录题目翻译题目描述输入格式输出格式样例#1样例输入#1样例输出#1样例#2样例输入#2样例输出#2样例#3样例输入#3样例输出#3题目简化题目思路AC代码题目翻译【题目描述】你决定用素数定理来做一个调查.众所周知,素数又被称为质数,其含义就是除了数字一和本身之外不能......
  • 算法题解--蓝桥云课跳跃
    题目蓝桥云课跳跃1.看完题目先写了个二维数组,然后就真的不懂了,最后找了个大概能懂的题解,思路大概是是建立坐标,再用递归求出所有路径,找出其中最大的权值和2.遇到的问题还是没思路,而且写下面使用递归的方法时光出错,不是很熟练3.测试结果:4.收获:学习过的static终于派上了用场,......