最小瓶颈路

题目描述

给定一个包含 n 个节点和 m 条边的图,每条边有一个权值。 你的任务是回答 k 个询问,每个询问包含两个正整数 s 和 t 表示起点和终点,要求寻找从 s 到 t 的一条路径,使得路径上权值最大的一条边权值最小。

输入格式

第一行包含三个整数 n、m、k,分别表示 n 个节点, m 条路径, k 个询问。

接下来 m 行,每行三个整数 u, v, w, 表示一个由 u 到 v 的长度为 w 的双向边。

再接下来 k 行,每行两个整数 s, t,表示询问从 s 连接到 t 的所有路径中单边长度最大值的最小值。

输出格式

输出包含 k 行,每一行包含一个整数 p。p 表示 s 连接到 t 的所有路径中单边长度最大值的最小值。另外,如果 s 到 t 没有路径相连通,输出 -1 即可。

样例输入

8 11 3
1 2 10
2 5 50
3 4 60
7 5 60
3 6 30
1 5 30
6 7 20
1 7 70
2 3 20
3 5 40
2 6 90
1 7
2 8
6 2

样例输出

30
-1
30

数据范围与提示
对于 30% 的数据 n≤ ≤

100,m≤ ≤

1000,k≤ ≤

100,w≤ ≤

1000
对于 70% 的数据 n≤ ≤

1000,m≤ ≤

10000,k≤ ≤

1000,w≤ ≤

100000
对于 100% 的数据 n≤ ≤

1000,m≤ ≤

100000,k≤ ≤

1000,w≤ ≤

10000000
本题可能会有重边。 为了避免 Special Judge,本题所有的 w 均不相同。



根据常识可得“从 s 连接到 t 的所有路径中单边长度最大值要最小”,那么他们走过的边肯定在当前图的最小生成树里

1.求出最小生成树,建新图

2.求一棵树里两点关系->LCA

3.在求最小生成树时,我用了并查集维护连通性-》在后面询问时来判断两点是否在同一连通块里

#include<bits/stdc++.h>
#define re return
#define lowbit(x) (x&(-x))
#define dec(i,l,r) for(int i=l;i>=r;--i)
#define inc(i,l,r) for(int i=l;i<=r;++i)
const int maxn=1005,maxm=200005;
using namespace std;
template<typename T>inline void rd(T&x)
{
	char c;bool f=0;
	while((c=getchar())<‘0‘||c>‘9‘)if(c==‘-‘)f=1;
	x=c^48;
	while((c=getchar())>=‘0‘&&c<=‘9‘)x=x*10+(c^48);
	if(f)x=-x;
} 

int n,m,q,deep[maxn],hd[maxn],fa[maxn],f[maxn][25],dis[maxn][25];

struct node{
	int fr,to,nt,val;
	bool operator<(node x)const
	{
		re val<x.val;
	}
}e[maxn<<1],e1[maxm]; 

inline int find(int x)
{
	re x==fa[x]?x:fa[x]=find(fa[x]);
}

inline void dfs(int x,int fa)
{
	deep[x]=deep[fa]+1;
	for(int i=0;f[f[x][i]][i];++i)
	{
		f[x][i+1]=f[f[x][i]][i];
		dis[x][i+1]=max(dis[x][i],dis[f[x][i]][i]);
	}
		for(int i=hd[x];i;i=e[i].nt)
		{
			int v=e[i].to;
			if(v!=fa)
			{
				f[v][0]=x;
				dis[v][0]=e[i].val;
				dfs(v,x);
			}
		}
}

inline int LCA(int x,int y)
{
	int ans=0;
	if(deep[x]<deep[y])x^=y^=x^=y;
	dec(i,24,0)
	if(deep[f[x][i]]>=deep[y])
	{
		ans=max(ans,dis[x][i]);
		x=f[x][i];
	}
	if(x==y)re ans;

	dec(i,24,0)
	if(f[x][i]!=f[y][i])
	{
		ans=max(ans,dis[x][i]);
		ans=max(ans,dis[y][i]);
		x=f[x][i];
		y=f[y][i];
	}
	re max(ans,max(dis[x][0],dis[y][0]));
}
int main()
{

	int x,y,z;
	rd(n),rd(m);rd(q);
	inc(i,1,m)
	{
		rd(x),rd(y),rd(z);
		e1[i]=(node){x,y,0,z};
	}

	sort(e1+1,e1+m+1);

	int cnt=0,k=0;
	inc(i,1,n)fa[i]=i;
	inc(i,1,m)
	{
		int x=e1[i].fr,y=e1[i].to,w=e1[i].val;
		int f1=find(fa[x]),f2=find(fa[y]);
		if(f1!=f2)
		{
			e[++k]=(node){x,y,hd[x],w};hd[x]=k;
			e[++k]=(node){y,x,hd[y],w};hd[y]=k;
			++cnt;
			fa[f1]=f2;
			if(cnt==n-1)break;
		}
	}

	inc(i,1,n)
	if(!deep[i])dfs(i,0);
	int s,t;
	inc(i,1,q)
	{
		rd(s),rd(t);
		if(i==27)
		x=1;
		if(find(s)!=find(t))printf("-1\n");
		else printf("%d\n",LCA(s,t));
	}
	re 0;
}

  

原文地址:https://www.cnblogs.com/lsyyy/p/11291441.html

时间: 2024-08-04 01:06:35

最小瓶颈路的相关文章

最小瓶颈路 Uva 534 Frogger

说明:关于Uva的题目,可以在vjudge上做的,不用到Uva(那个极其慢的)网站去做. 最小瓶颈路:找u到v的一条路径满足最大边权值尽量小 先求最小生成树,然后u到v的路径在树上是唯一的,答案就是这条路径. Uva 534 Frogger Time Limit: 3000MS 64bit IO Format: %lld & %llu Description Freddy Frog is sitting on a stone in the middle of a lake. Suddenly h

HDU 4081Qin Shi Huang&amp;#39;s National Road System(最小生成树+最小瓶颈路)

 题意:秦始皇要修路.把N个城市用N-1条边连通.且他希望花费最小,可是这时候有一个多管闲事的道士出来说他有魔法能够帮助秦始皇变成一条路.可是仅仅能变出一条. 可是.两个人对修路的法案存在歧义,道士希望修路能够给很多其它的百姓带来福利.而秦始皇希望修路要尽量使花费小.最后,秦始皇拿出了一个公式A/B.A表示两个城市的人数,B表示出了用魔法变出来的路外.最短的总距离. 如今要你求出A/B的最大值. 思路:枚举连接哪两个城市.由于这条边是免费的.我们要求算上这条边的最小生成树.假设每次都求一次最

UVALive 5713 Qin Shi Huang&#39;s National Road System秦始皇修路(MST,最小瓶颈路)

题意: 秦始皇要在n个城市之间修路,而徐福声可以用法术位秦始皇免费修1条路,每个城市还有人口数,现要求徐福声所修之路的两城市的人口数之和A尽量大,而使n个城市互通需要修的路长B尽量短,从而使得A/B最大.问A/B最大是多少?(1000个城市) 思路: 老徐可免费修得1条路,那么剩下最多也只需要修n-2条路了,这n-2条路要尽量挑短的,而老徐的那条无所谓长短,只要两城人口尽量多即可.这是没有什么贪心策略的,因为老徐所修之路会影响MST的权值之和的大小.穷举所有城市对要O(n*n),再求次MST需要

UVA 10457 - Magic Car(最小瓶颈路)

UVA 10457 - Magic Car 题目链接 题意:m条路,每条路上必须维持速度v,现在有一辆车,启动能量和结束能量为a, b,途中消耗能量为经过路径最大速度减去最小速度,现在每次循环给定起点终点,问最小能量花费 思路:最小瓶颈路,利用kruskal去搞 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 205; con

最小瓶颈路与次小生成树

简介: 最小生成树是图论里面一类经典问题,可以有很多种变形,其中最小瓶颈路和次小生成树就是两种比较经典的变形.最小瓶颈路就是在两个结点之间求一条最长边最短的路径,而次小生成树则是所有生成树中权值排名第二的生成树(可以和最小生成树相等).下面我们分别来看看这两个问题. 最小瓶颈路: 给定一个加权无向图,并给定无向图中两个结点u和v,求u到v的一条路径,使得路径上边的最大权值最小.这个问题可以稍微加强一下,即求很多对结点之间的最小瓶颈路. 无向图中,任意两个结点的最小瓶颈路肯定在最小生成树上.因此,

BZOJ 3732 Network 最小瓶颈路

题目大意:给出一个无向边,很多询问,问x,y两地之间的最长路最短是多少. 思路:乍一看好像是二分啊.的确这个题二分可以做,但是时间会慢很多,有的题直接就T掉(NOIP2013货车运输).其实这个题的模型就是最小瓶颈路模型.解法就是把无向图变成一个最小生成树,然后两点之间的最长路就是满足题意的答案. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm&g

【UVA534】Frogger 最小瓶颈路

题目大意:给定一张 N 个点的完全图,求 1,2 号节点之间的一条最小瓶颈路. 题解:可知,最小瓶颈路一定存在于最小生成树(最小瓶颈树)中.因此,直接跑克鲁斯卡尔算法,当 1,2 号节点在同一个联通块时,即可停止算法,并输出答案即可. 代码如下 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using n

洛谷 P1967 货车运输 Label: 倍增LCA &amp;&amp; 最小瓶颈路

题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入输出格式 输入格式: 输入文件名为 truck.in. 输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道 路. 接下来 m 行每行 3 个整数 x. y. z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z

uva 10457(最小瓶颈路)

比赛的时候读错题了,赛后非要建最小生成树然后dfs暴搜,有人告诉我不行,我还非要改一遍,改了一年,想明白了,不能保证下限,比如2,3,5能使两个点连同,4,5也能的话,就不对了,想想我也是个铁头娃 #include <iostream> #include <cstring> #include <algorithm> #include <cstdio> #include <queue> using namespace std; const int