[CF827D]Best Edge Weight

Posted by Dispwnl on September 29, 2018

题目

题目大意

给定一个带权无向图

对于每条边,求其他边不变时这条边能出现在这个图的每一个最小生成树上,这条边满足条件的最大权值是多少

Examples

input

4 4
1 2 2
2 3 2
3 4 2
4 1 3

output

2 2 2 1 

input

4 3
1 2 2
2 3 2
3 4 2

output

-1 -1 -1 

题解

如图,绿边表示非树边,蓝边表示树边,很容易看出来一条非树边的答案应该是ta两端之间树边的最大值$-1$,这样ta才能不被替换掉

树边的答案需要非树边来更新

如图,红边表示要更新的树边,因为非树边一定不小于树边,树边答案应该为非树边权值$-1$,即保证最小生成树只能选ta这条边

所以树边答案为两端包含ta的非树边的最小值$-1$

代码

# include<bits/stdc++.h>
using namespace std;
const int MAX=2e5+1;
struct p{
	int x,y,dis,id;
	bool operator< (const p &a)
	const{
		return dis<a.dis;
	}
}c[MAX],cc[MAX<<1];
int n,m,num;
int d[MAX],h[MAX],fa[MAX],Ans[MAX],ID[MAX];
int f[MAX][19],maxn[MAX][19];
bool use[MAX];
int read()
{
	int x(0);
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar());
	for(;isdigit(ch);x=x*10+ch-48,ch=getchar());
	return x;
}
void dfs(int x,int fa=0)
{
	d[x]=d[fa]+1,f[x][0]=fa;
	for(int i=h[x];i;i=cc[i].x)
	  if(cc[i].y!=fa) maxn[cc[i].y][0]=cc[i].dis,ID[cc[i].y]=cc[i].id,dfs(cc[i].y,x); 
}
int LCA(int x,int y)
{
	if(d[x]>d[y]) swap(x,y);
	int D=d[y]-d[x];
	for(int i=0;(1<<i)<=D;++i)
	  if((1<<i)&D) y=f[y][i];
	if(x==y) return x;
	for(int i=18;i>=0;--i)
	  if(f[y][i]!=f[x][i]) x=f[x][i],y=f[y][i];
	return f[x][0];
}
void add(int x,int y,int dis,int id)
{
	cc[++num]=(p){h[x],y,dis,id},h[x]=num;
	cc[++num]=(p){h[y],x,dis,id},h[y]=num;
}
void init()
{
	for(int i=1;i<=18;++i)
	  for(int j=1;j<=n;++j)
	    f[j][i]=f[f[j][i-1]][i-1],maxn[j][i]=max(maxn[j][i-1],maxn[f[j][i-1]][i-1]);
}
int GET_DIS(int x,int y)
{
	int ans=0;
	for(int i=18;i>=0;--i)
	  if(d[f[x][i]]>=d[y]) ans=max(ans,maxn[x][i]),x=f[x][i];
	return ans;
}
int find(int x)
{
	if(fa[x]!=x) fa[x]=find(fa[x]);
	return fa[x];
}
void change(int x,int y,int dis)
{
	int qwq=find(x);
	while(d[qwq]>d[y]) 
	Ans[ID[qwq]]=min(Ans[ID[qwq]],dis),fa[qwq]=find(f[qwq][0]),qwq=fa[qwq];
}
int main()
{
	n=read(),m=read();
	for(int i=1;i<=n;++i)
	  fa[i]=i;
	for(int i=1;i<=m;++i)
	  c[i].x=read(),c[i].y=read(),c[i].dis=read(),c[i].id=i,Ans[i]=2e9;
	sort(c+1,c+1+m);
	for(int i=1,L=0;i<=m;++i)
	  {
	  	if(L==n-1) break;
	  	int r1=find(c[i].x),r2=find(c[i].y);
	  	if(r1==r2) continue;
	  	fa[r1]=r2,add(c[i].x,c[i].y,c[i].dis,c[i].id),use[i]=1;
	  }
	for(int i=1;i<=n;++i)
	  fa[i]=i;
	dfs(1),init();
	for(int i=1,lca;i<=m;++i)
	  if(!use[i])
	  lca=LCA(c[i].x,c[i].y),Ans[c[i].id]=max(GET_DIS(c[i].x,lca),GET_DIS(c[i].y,lca))-1,change(c[i].x,lca,c[i].dis-1),change(c[i].y,lca,c[i].dis-1);
	for(int i=1;i<=m;++i)
	  printf("%d ",Ans[i]==2e9?-1:Ans[i]);
	return 0;
}