• [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++

  • 相关阅读:
    2020软件工程个人作业06——软件工程实践总结作业
    git上传文件夹内容
    git常用命令(部分)
    java命令行输入参数
    2020软件工程作业05
    软件工程——问题清单
    2020软件工程作业04
    2020软件工程作业03
    2020软件工程作业02
    问题清单
  • 原文地址:https://www.cnblogs.com/wzc521/p/11566697.html
Copyright © 2020-2023  润新知