1. 程式人生 > >JZOJ5914. 【NOIP2018模擬10.19】盟主的憂慮

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;
}