JZOJ5914. 【NOIP2018模拟10.19】盟主的忧虑

Description

江湖由 N 个门派(2≤N≤100,000,编号从 1 到 N)组成,这些门派之间有 N-1 条小道将他们连接起来,每条道路都以“尺”为单位去计量,武林盟主发现任何两个门派都能够直接或者间接通过小道连接。
虽然整个江湖是可以互相到达的,但是他担心有心怀不轨之徒破坏这个武林的安定,破坏小道,于是武林盟主又秘密地修建了 M 条密道(1≤M≤100,000),但每条小道距离都不超过10亿尺。
果不其然,最近一个名叫“太吾”的组织意欲破坏武林的小道,请你帮盟主想想办法,如果门派 A 到门派 B 的直连小道被破坏,从 A 走到 B 的所有路径中,经过密道的距离最少是多少?

Data Constraint

30%数据:N<=300,M<=1000
50%数据:N<=1000,M<=1000
70%数据:N<=5000,M<=5000
对于另外15%的数据点:树是一条链
100%数据:N,M<=100,000

题解

根据树的性质可以知道,
某条树边被删掉之后,最多只会有一条被替换。
将其他边按照边权排序,
依次插入,
每次如果它在树上构成环的边之前没有被其他边的边权赋值为这条边。
用并查集维护就好了。

code

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#define N 100003
#define P putchar
#define G getchar
using namespace std;
char ch;
void read(int &n)
{
	n=0;
	ch=G();
	while((ch<'0' || ch>'9') && ch!='-')ch=G();
	int w=1;
	if(ch=='-')w=-1,ch=G();
	while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
	n*=w;
}

void write(int x){if(x>9) write(x/10);P(x%10+'0');}

int n,m,nxt[N*2],to[N*2],lst[N],x,y,t,tot;
int fa[N],id[N],f[17][N],ans[N],dep[N];

struct node
{
	int x,y,z;
}a[N];

bool cmp(node a,node b){return a.z<b.z;}
int get(int x){return fa[x]=((fa[x]^x)?get(fa[x]):x);}

void dfs(int x)
{
	fa[x]=x;dep[x]=dep[f[0][x]]+1;
	for(int i=lst[x];i;i=nxt[i])
		if(to[i]^f[0][x])f[0][to[i]]=x,id[to[i]]=i>>1,dfs(to[i]);
}

void ins(int x,int y)
{
	nxt[++tot]=lst[x];
	to[tot]=y;
	lst[x]=tot;
}

int lca(int x,int y)
{
	if(dep[x]<dep[y])swap(x,y);
	for(int j=16;j+1;j--)
		if(dep[f[j][x]]>=dep[y])x=f[j][x];
	if(x==y)return x;
	for(int j=16;j+1;j--)
		if(f[j][x]^f[j][y])x=f[j][x],y=f[j][y];
	return f[0][x];
}

int main()
{
	freopen("worry.in","r",stdin);
	freopen("worry.out","w",stdout);
	
	read(n);read(m);tot=1;
	for(int i=1;i<n;i++)read(x),read(y),ins(x,y),ins(y,x);
	for(int i=1;i<=m;i++)read(a[i].x),read(a[i].y),read(a[i].z);
	sort(a+1,a+1+m,cmp);dfs(1);	
	for(int j=1;j<17;j++)
		for(int i=1;i<=n;i++)
			f[j][i]=f[j-1][f[j-1][i]];
	memset(ans,128,sizeof(ans));
	for(int i=1;i<=m;i++)
	{
		x=a[i].x;y=a[i].y;t=lca(x,y);t=get(t);
		for(;get(x)^t;fa[x]=get(f[0][x]))x=get(x),ans[id[x]]=a[i].z;
		for(;get(y)^t;fa[y]=get(f[0][y]))y=get(y),ans[id[y]]=a[i].z;
	}
	for(int i=1;i<n;i++)if(ans[i]<0)puts("-1");else write(ans[i]),P('\n');
	return 0;
}

猜你喜欢

转载自blog.csdn.net/lijf2001/article/details/83240382
今日推荐