[CSP-S模拟测试]:weight(Kruskal+树链剖分)

题目描述

给你一个$n$个点$m$条边的带边权的无向图(无重边,无自环),现在对于每条边,问你这条边的权值最大可以是多大,使得这条边在无向图的所有最小生成树中?(边权都是整数)。


输入格式

第一行包含三个整数$n,m,a$表示点数和边数及特殊性质标记(如果$a=0$表示没有特殊性质,如果殊性质)。
接下来$m$行每行包含三个整数$u,v,w$表示有一条$u$和$v$之间的边,且边权为$w$。


输出格式

输出一行,包含$m$个数,第$i$个数表示第$i$条边对应的答案(如果某条边的权值可以取到$+infty$输出$-1$)。


样例

样例输入1:

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

样例输出1:

1 1 1 0

样例输入2:

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

样例输出2:

-1 -1 -1


数据范围与提示

特殊性质:$w=1$(对于所有边);
对于所有数据:$1leqslant u,vleqslant n,1leqslant wleqslant {10}^9$。


题解

对于一条边,分为两种情况:

  $alpha.$最小生成树上的边,那么它的最大值就是能代替它的最小边的边权$-1$。

  $eta.$不是最小生成树上的边,那么它的最大值就是最小生成树上那条边的边权$-1$。

对于如何求,用树链剖分就好了,代码稍长……

数据的输出有点问题,如果不在$1$节点的联通块中则输出$0$。

时间复杂度:$Theta(nlog^2 n)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
struct node{int fr,to,w,id;bool tr;}b[100001];
struct rec{int nxt,to,w,id;}e[200001];
int head[70001],cnt;
int maxb,dy[70001];
int n,m,a;
int f[70001];
int depth[70001],size[70001],id[70001],w[70001],son[70001],top[70001],pos[70001],fa[70001];
int trmax[280001],trmin[280001],lz[280001];
int ans[100001];
bool cmp(node a,node b){return a.w<b.w;}
void add(int x,int y,int w,int id)
{
	e[++cnt].nxt=head[x];
	e[cnt].to=y;
	e[cnt].w=w;
	e[cnt].id=id;
	head[x]=cnt;
}
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
void pre_dfs(int x)
{
	size[x]=1;
	for(int i=head[x];i;i=e[i].nxt)
		if(e[i].to!=fa[x])
		{
			depth[e[i].to]=depth[x]+1;
			fa[e[i].to]=x;
			dy[e[i].to]=e[i].id;
			w[e[i].to]=e[i].w;
			pre_dfs(e[i].to);
			size[x]+=size[e[i].to];
			if(size[e[i].to]>size[son[x]])son[x]=e[i].to;
		}
}
void pro_dfs(int x,int tp)
{
	top[x]=tp;
	id[x]=++cnt;
	pos[cnt]=x;
	if(son[x])pro_dfs(son[x],tp);
	for(int i=head[x];i;i=e[i].nxt)
		if(e[i].to!=fa[x]&&e[i].to!=son[x])pro_dfs(e[i].to,e[i].to);
}
void build(int x,int l,int r)
{
	trmin[x]=lz[x]=maxb+1;
	if(l==r)
	{
		trmax[x]=w[pos[l]];
		return;
	}
	int mid=(l+r)>>1;
	build(L(x),l,mid);
	build(R(x),mid+1,r);
	trmax[x]=max(trmax[L(x)],trmax[R(x)]);
}
void pushdown(int x)
{
	if(lz[x]==maxb+1)return;
	trmin[L(x)]=min(trmin[L(x)],lz[x]);
	trmin[R(x)]=min(trmin[R(x)],lz[x]);
	lz[L(x)]=min(lz[L(x)],lz[x]);
	lz[R(x)]=min(lz[R(x)],lz[x]);
	lz[x]=1<<30;
}
int ask(int x,int l,int r,int L,int R)
{
	if(R<l||r<L)return 0;
	if(L<=l&&r<=R)return trmax[x];
	int mid=(l+r)>>1;
	return max(ask(L(x),l,mid,L,R),ask(R(x),mid+1,r,L,R));
}
int query(int x,int y)
{
	int ret=0;
	while(top[x]!=top[y])
	{
		if(depth[top[x]]<depth[top[y]])swap(x,y);
		ret=max(ret,ask(1,1,n,id[top[x]],id[x]));
		x=fa[top[x]];
	}
	if(depth[x]>depth[y])swap(x,y);
	if(id[x]<id[y])ret=max(ret,ask(1,1,n,id[x]+1,id[y]));
    return ret;
}
void change(int x,int l,int r,int L,int R,int w)
{
	if(R<l||r<L)return;
	if(L<=l&&r<=R)
	{
		trmin[x]=min(trmin[x],w);
		lz[x]=min(lz[x],w);
		return;
	}
	int mid=(l+r)>>1;
	pushdown(x);
	change(L(x),l,mid,L,R,w);
	change(R(x),mid+1,r,L,R,w);
	trmin[x]=min(trmin[L(x)],trmin[R(x)]);
}
int update(int x,int y,int w)
{
	int ret=0;
	while(top[x]!=top[y])
	{
		if(depth[top[x]]<depth[top[y]])swap(x,y);
		change(1,1,n,id[top[x]],id[x],w);
		x=fa[top[x]];
	}
	if(depth[x]>depth[y])swap(x,y);
	if(id[x]<id[y])change(1,1,n,id[x]+1,id[y],w);
    return ret;
}
void getans(int x,int l,int r)
{
	if(l==r)
	{
		ans[dy[pos[l]]]=trmin[x];
		if(ans[dy[pos[l]]]==maxb+1)ans[dy[pos[l]]]=0;
		ans[dy[pos[l]]]--;
		return;
	}
	int mid=(l+r)>>1;
	pushdown(x);
	getans(L(x),l,mid);
	getans(R(x),mid+1,r);
}
int main()
{
	scanf("%d%d%d",&n,&m,&a);
	for(int i=1;i<=n;i++)f[i]=i;
	for(int i=1;i<=m;i++)
	{
		int x,y,w;
		scanf("%d%d%d",&x,&y,&w);
		b[i]=(node){x,y,w,i,0};
		maxb=max(maxb,w);
	}
	sort(b+1,b+m+1,cmp);
	for(int i=1;i<=m;i++)
		if(find(b[i].fr)!=find(b[i].to))
		{
			f[find(b[i].fr)]=find(b[i].to);
			add(b[i].fr,b[i].to,b[i].w,b[i].id);
			add(b[i].to,b[i].fr,b[i].w,b[i].id);
			b[i].tr=1;
		}
	cnt=0;
	pre_dfs(1);
	pro_dfs(1,1);
	build(1,1,n);
	for(int i=1;i<=m;i++)
		if(!b[i].tr)
		{
			ans[b[i].id]=query(b[i].fr,b[i].to)-1;
			update(b[i].fr,b[i].to,b[i].w);
		}
	getans(1,1,n);
	for(int i=1;i<=m;i++)printf("%d ",ans[i]);
	return 0;
}

rp++

原文地址:https://www.cnblogs.com/wzc521/p/11566697.html