第十一屆藍橋杯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 '\n'
#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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM