zoukankan      html  css  js  c++  java
  • 蓝桥杯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

    地上佳人若非卿 月下小酌亦无心
  • 相关阅读:
    腾讯开放平台 手机QQ登录 错误码:110406 解决办法
    比较酷的安卓软件
    Top 10 Methods for Java Arrays
    Feathers UI 性能优化
    Starling中通过PivotX 和 PivotY 修改原点
    Adobe AIR 中为不同尺寸和分辨率屏幕适配
    Feathers组件的宽度或高度属性,为什么我得到的值是0
    "Type Coercion failed" Error in FlashBuilder 4.7
    正则表达式中的特殊字符
    单体内置对象 Global 和 Math
  • 原文地址:https://www.cnblogs.com/zengbiaojie/p/13805577.html
Copyright © 2011-2022 走看看