• 蓝桥杯2020.7(C++ B组) 网络分析


    题目链接

    思路

    一开始想着直接并查集,然后开个结果数组,每次传递信息,都假设这个信息是从父节点开始传递的,让父节点的结果数组加上发送的消息数量就可以,然后子节点的信息数,就是子节点的结果集加上父节点的结果集,就像下面,假设有两个点(1,2),进行两个操作,将1和2连接,在2上发送信息

    这个时候就会有一个问题,假设在1还没有和2连接的时候就发送了消息,然后再连接,此时查询结果,会产生2没连在1上时发送的消息也被算在2内的现象,即:

    很明显,结果应该为 1 和 0 ,但是依照之前的思路结果却为 1 和 1 ,此时我们考虑连上一条边,就把这条边先减去父节点消息数,有点差分的意思,像下图

    此时结果就正确了。非常自信的认为自己正确了,自信交卷准备一发入魂,结果就看到了
    WRONG ANSWER

    开始怀疑人生,到底是哪里出了问题,跑去看了一下测试点,手动用草稿纸模拟了一边,终于让我发现了问题所在
    如果连接的两个点,本身自身就带着一堆的子节点,两个父节点相连,让连上去的父节点减去最终的父节点的值,连上去的父节点没问题,但是它的所有子节点都没有去减掉父节点的值,类似下图

    发现问题所在,那么接下来就是解决问题了,跑去上了个厕所,灵感喷涌而出,都说厕所很有灵感果然是真的(。。。)
    我们在每一次加上点的时候,都先把被加上点的所有子节点都去减去最终父节点的值,同时加上被加上点的值就可以了,只需要开一个辅助的vector就能完美的完成这件事,思路清奇,非常完美。

    代码

    #include<iostream>
    #include<vector>
    using namespace std;
    
    int father[10005];
    
    int result[10005];
    vector<int> v[10005];
    void init(int n){
        for(int i = 1;i <= n;i++)
            father[i] = i;
    }
    
    int find(int x){
        return x == father[x] ? x : father[x] = find(father[x]);
    }
    
    void unite(int x , int y){
        int a = find(x);
        int b = find(y);
        int m = min(a , b);
        int ma = max(a , b);
        father[a] = m;
        father[b] = m;
        int len = v[ma].size();
        v[m].push_back(ma);
        for(int i = 0; i < len ;i++){
            v[m].push_back(v[ma][i]);
            result[v[ma][i]] -= result[m];
            result[v[ma][i]] += result[ma];
        }
        result[ma] -= result[m];
        v[ma].clear();
    }
    
    int main(){
        int n , m;
        cin >> n >> m ;
        init(n);
        for(int i = 1;i <= m;i++){
            int op , p , t;
            cin >> op >> p >> t;
            if(op == 1){
                if(find(p) == find(t))
                    continue;
                unite(p , t);
            }else{
                int x = find(p);
                result[x] += t;
            }
        }
        for(int i = 1;i <= n;i++){
            int x = find(i);
            if(x == i){
                cout << result[i] << " ";
            }else{
                cout << result[i] + result[x] << " ";
            }
        }
        cout << endl;
        return 0;
    }
    

    终于一道简单题 ACCEPT

    地上佳人若非卿 月下小酌亦无心
  • 相关阅读:
    【Canvas】(1)---概述+简单示例
    【jQuery】(8)---jquery Ajax
    lastlogon
    windows server core 2016 IIS远程管理的那些坑
    开机手机显示存储空间不足某些系统功能可能无法正常使用,而且无法取消这个界面,导致手机停在这个界面无法操作。
    javascript prototype理解
    微信小程序诡异错误this.setData报错
    转:goproxy和go modules的初步使用
    真机调试No target device的解决(android studio)3.4.1
    unable to access android sdk add-on list的解决
  • 原文地址:https://www.cnblogs.com/zengbiaojie/p/13805577.html
Copyright © 2020-2023  润新知