2019 UESTC ACM Training for Data Structures[B]

问题描述:给一棵n个节点的树,给出q次询问,每次询问u,v节点的路径上的边权最小值。

先将输入的边变负存入,然后按从小到大排序(对应到原边是从大到小)。
然后依次枚举每一条边,每一条边的端点判断是否在同一集合中,如果不在,则通过并查集合并。
注意合并时要创建新的节点,将这两个端点接入这个新的节点中。
然后用val数组表示每个节点的“权值”。对于新创建的节点,将权值赋成合并时两个端点的边权。
这样,我们新建的树的叶子节点就全都是原先的

#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=2e5+5;
const int maxs=19;
struct Edge{
	int from,to,d;
	Edge(int from,int to,int d):from(from),to(to),d(d){};
	bool operator <(const Edge &h)const{
		return dG[2*maxn];
vectoredges;
vectortedges;
int n,q,dis[maxn],fat[maxn],val[maxn],cur,fa[maxn][20];
int depth[maxn];
void add_edges(int from,int to,int d){
	d=-d;
	edges.push_back(Edge(from,to,d));
	G[from].push_back(edges.size()-1);
	edges.push_back(Edge(to,from,d));
	G[to].push_back(edges.size()-1);
}
int getfa(int x){return fat[x]==x?x:fat[x]=getfa(fat[x]);}
void build_tree(){//并查集合并,建立新树
	cur=n;
	for(int i=1;i<=2*n;i++)fat[i]=i;
	for(int i=0;i=0;i--)
	    if(fa[x][i]!=fa[y][i]){ x=fa[x][i]; y=fa[y][i]; }
	return fa[x][0];
}
int main(){
	scanf("%d%d",&n,&q);
	int x,y,z;
	for(int i=1;i

树的节点,对于询问的两点u,v LCA(u,v)的权值的相反数即为所求的答案。

你可能感兴趣的:(树)