BZOJ 3732 Network Kruskal+倍增LCA

题目大意:给定一个n个点m条边的无向连通图,k次询问两点之间所有路径中最长边的最小值

NOIP2013 货车运输,几乎就是原题。。。只不过最小边最大改成了最大边最小。。。

首先看到最大值最小第一反应二分答案 但是二分答案O(kmlogn)明显做不了 这里我们考虑最小生成树

先生成一棵最小生成树,然后每次询问利用倍增LCA求出路径上的最大权值即可

本蒟蒻居然把LCA写挂了。。。 而且样例还过了。。。 伤不起啊。。。

90%达成 剩下一道刷点啥呢。。。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct edge{
	int x,y,f;
	bool operator < (const edge &y) const
	{
		return f < y.f;
	}
}edges[30300];
struct abcd{
	int to,f,next;
}table[30300];
int head[15100],tot;
int n,m,k;
int fa[15100][20],f_max[15100][20],dpt[15100];
int belong[15100];
int find(int x)
{
	if(!belong[x]||belong[x]==x)
		return belong[x]=x;
	return belong[x]=find(belong[x]);
}
void add(int x,int y,int z)
{
	table[++tot].to=y;
	table[tot].f=z;
	table[tot].next=head[x];
	head[x]=tot;
}
void dfs(int x)
{
	int i;
	dpt[x]=dpt[fa[x][0]]+1;
	for(i=head[x];i;i=table[i].next)
	{
		if(table[i].to==fa[x][0])
			continue;
		fa[table[i].to][0]=x;
		f_max[table[i].to][0]=table[i].f;
		dfs(table[i].to);
	}
}
int Query(int x,int y)
{
	int j,re=0;
	if(dpt[x]<dpt[y])
		swap(x,y);
	for(j=14;~j;j--)
		if(dpt[ fa[x][j] ]>=dpt[y])
			re=max(re,f_max[x][j]),x=fa[x][j];
	if(x==y)
		return re;
	for(j=14;~j;j--)
		if(fa[x][j]!=fa[y][j])
		{
			re=max(re,f_max[x][j]);
			re=max(re,f_max[y][j]);
			x=fa[x][j];
			y=fa[y][j];
		}
	re=max(re,f_max[x][0]);
	re=max(re,f_max[y][0]);
	return re;
}
int main()
{
	int i,j,x,y;
	cin>>n>>m>>k;
	for(i=1;i<=m;i++)
		scanf("%d%d%d",&edges[i].x,&edges[i].y,&edges[i].f);
	sort(edges+1,edges+m+1);
	for(i=1;i<=m;i++)
	{
		int fx=find(edges[i].x),fy=find(edges[i].y);
		if(fx!=fy)
		{
			belong[fx]=fy;
			add(edges[i].x,edges[i].y,edges[i].f);
			add(edges[i].y,edges[i].x,edges[i].f);
		}
	}
	dfs(1);
	for(j=1;j<=14;j++)
		for(i=1;i<=n;i++)
			fa[i][j]=fa[ fa[i][j-1] ][j-1],f_max[i][j]=max( f_max[i][j-1] , f_max[ fa[i][j-1] ][j-1] );
	for(i=1;i<=k;i++)
	{
		scanf("%d%d",&x,&y);
		printf("%d\n", Query(x,y) );
	}
}
时间: 2024-10-07 05:17:49

BZOJ 3732 Network Kruskal+倍增LCA的相关文章

BZOJ 3732 Network Kruskal重构树

题目大意:给定一个n个点m条边的无向连通图,k次询问两点之间所有路径中最长边的最小值 Kruskal+倍增LCA做法见http://blog.csdn.net/popoqqq/article/details/39755703 LCT做法见http://blog.csdn.net/popoqqq/article/details/39929277 Kruskal重构树真是强大--一不小心手滑就RANK1啥的-- 每加入一条边时,我们并不链接这条边的两端点,而是把这条边两端点所在并查集的根连接起来,而

【BZOJ3732】 Network Kruskal+倍增lca

Description 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 < = d_j < = 1,000,000,000). 现在有 K个询问 (1 < = K < = 15,000). 每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少? Input 第一行: N, M, K. 第2..M+1行: 三个正整数

BZOJ 2791 Poi2012 Rendezvous 倍增LCA

题目大意:给定一棵内向森林,多次给定两个点a和b,求点对(x,y)满足: 1.从a出发走x步和从b出发走y步会到达同一个点 2.在1的基础上如果有多解,那么要求max(x,y)最小 3.在1和2的基础上如果有多解,那么要求min(x,y)最小 4.如果在1.2.3的基础上仍有多解,那么要求x>=y 因此那个x>=y是用来省掉SPJ的,不是题目要求- - 容易发现: 如果a和b不在同一棵内向树上,显然无解,否则一定有解 定义根为从一个点出发能走到的第一个环上点,如果a和b的根相同,则到达LCA是

BZOJ 1787 AHOI2008 紧急集合 倍增LCA

题目大意:给定一棵树,多次询问到三个点距离之和最小的点和距离 首先易知到两个点距离之和最小的点一定在两点间的路径上 于是到三个点距离之和最小的点一定在两两之间路径的交点上 然后很容易就会知道这个交点一定是其中两个点的LCA(其实是我不会证) 此外为什么不会是三个点共同的LCA呢?因为三个点共同的LCA一定是至少一对点的LCA 证明略(其实我也不会证) 然后就是枚举两两之间的LCA 求一下距离 取最小即可 然后就是倍增LCA的问题了 我的倍增LCA怎么又挂了 还能不能写对了0.0 #include

bzoj 3732: Network 树上两点边权最值

http://www.lydsy.com/JudgeOnline/problem.php?id=3732 首先想到,要使得最长边最短,应该尽量走最短的边,在MST上. 然后像LCA那样倍增娶个最大值 #include <bits/stdc++.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; const int ma

poj1330|bzoj3732|noip2013 货车运输 kruskal+倍增lca

学了一早上倍增,感觉lca还是tarjan好写. poj1330 1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 #include <algorithm> 5 #define DEG 20//2^20 6 #define maxn 10010 7 using namespace std; 8 struct node 9 { 10 int v, next; 11 }a[maxn*2

BZOJ 3732 Network

2016.1.28 纪念我BZOJ第一题 Description 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 < = d_j < = 1,000,000,000). 现在有 K个询问 (1 < = K < = 15,000). 每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少? Input 第一行: N,

BZOJ 2286 SDOI2011 消耗战 倍增LCA+单调栈

题目大意:给定一棵树,边上有边权,m次询问,每次选定一些关键点,求将1号节点与所有关键点都切断所需的最小花销 关键点的总数<=50W 首先我们考虑暴力想法 令f[x]表示切断以x为根的子树中所有关键点的最小花销 g[x]表示x是不是关键点 那么对于x的每个子节点y有f[x]=Σmin(g[y]?INF:f[y],Distance(x,y) ) 这样每次暴力做一遍树形DP,时间复杂度是O(n*m)的 现在由于每次询问的点数不一定会达到n的级别,对所有节点进行DFS非常浪费 我们可以将询问的关键点拿

HDU3078 Network (倍增LCA算法求树链)

题意: 一棵无向树,输入点数和操作数,下面一行n个值代表每个点的权.下面n-1行是树边 操作分为 0 x w ,表示把点x的权改为w: k a b , 求出,从a到b的路径中,第k大的点权 题解: 对于每组询问,先求出两点的LCA,再从两点分别向LCA遍历,保存路径上所有的点权,排序输出第K大即可~ #include<cstdio> #include<algorithm> #include<cstring> #include<vector> using na