第十一届蓝桥杯C/C++ J题网络分析(带权并查集水题)

题意:给你n个点,m次操作。操作1是合并a和b;操作2是在p及其连通块内所有点上增加大小为t的值。为你m次操作之后,各个点的大小是多少?

评测用例及其得分:

对于 30% 的评测用例,1 ≤ n ≤ 20,1 ≤ m ≤ 100。
对于 50% 的评测用例,1 ≤ n ≤ 100,1 ≤ m ≤ 1000。
对于 70% 的评测用例,1 ≤ n ≤ 1000,1 ≤ m ≤ 10000。
对于所有评测用例,1 ≤ n ≤ 10000,1 ≤ m ≤ 100000,1 ≤ t ≤ 100。

个人想说的话:本来是不想写题解的,因为没必要,但是网上好像真没有人写出满分正解目前为止,那我就写写吧。

解法:看到一道题就需要分析复杂度,做题千万不要无脑去莽,很多人上来就是一个add边+bfs暴搜修改权值,这当然可以,但是你只能得70%的分。(最坏复杂度:先1000次操作1建边,最后建到1000个点的双联通图;再9000次操作2bfs,复杂度是O(9000*1000+1000),大概是O(9e6)的复杂度,能过70%样例。)

但是这种做法在ACM赛制里还是TLE。

所以我们需要考虑优化,看到这种合并题,第一反应应该就是dsu啊?那我们考虑怎么搞并查集,普通并查集显然8太行(或者维护起来很麻烦),观察性质可以知道,我们只需要维护当前点p及其当前点p的root的差值就可以了。那就好办了啊,带权并查集直接上啊,所以每个点最后的结果就是它与它祖先root的差值+root自身的值就可以了。

我们对于操作1,那就是非连通块的话合并并且更新其d值,已经是连通块就continue掉。

我们对于操作2,其实意思就是在他祖先点进行修改就可以了,因为我们要求的最终结果是祖先自己的值+该点与祖先的差值。

不知道你们懂了没qwq,附上我自己写的代码,欢迎Hack~

/*
    Author: Anonytt
    Date: 08/08/20 20:35
*/

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define ll long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define endl '
'
#define eps 0.000000001
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
const int maxn=1e4+5;
int fa[maxn],d[maxn],now[maxn],n,m;
int find(int x){
    if(x!=fa[x]){
        int temp=fa[x];
        fa[x]=find(fa[x]);
        d[x]+=d[temp];
    }
    return fa[x];
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) fa[i]=i;
    while(m--){
        int op;scanf("%d",&op);
        if(op==1){
            int a,b;scanf("%d%d",&a,&b);
            int eu=find(a),ev=find(b);
            if(eu!=ev){
                fa[ev]=eu;
                d[ev]=now[ev]-now[eu];
            }
        }
        else{
            int p,t;scanf("%d%d",&p,&t);
            int rt=find(p);
            now[rt]+=t;            
        }
    }
    rep(i,1,n){
        printf("%d ",now[find(i)]+d[i]);
    }
    puts("");    
}
/*
4 8
1 1 2
2 1 10
2 3 5
1 4 1
2 2 2
1 1 2
1 2 4
2 2 1
*/
View Code
原文地址:https://www.cnblogs.com/Anonytt/p/13460202.html