zoukankan      html  css  js  c++  java
  • cf 1243 D. 0-1 MST(队列瞎搞)

    题意:

    有n个点的无向完全图,有m条边的边权为1,其余都为0,求最小生成树的权值。

    思路:

    初始时,生成树的大小为0,先把点1加入进去,然后把那种不需要花费权值,就可以加入的点,先加入进去,

    因为每加入一些点,就会有一些点,从需要花费权值 转变为 不需要花费权值,所以要优先加入这样的点。

    怎么判断这个点加入需不需要花费权值,

    每次加入一个点的时候,就把与这个点相连的点加1,如果这个点的值,等于生成树的大小,那么就说明它与生成树中所有的点都相连,所以它需要花费权值。

    如果未在生成树中的所有点的值,都等于生成树大小了,那就随便加入一个点,那就很可能会再解锁一些点。

    就这样循环搞,直到所有点都加入生成树了为止。

    用队列实现。

    这样的复杂度不好算,于是,假设最糟糕的情况(或许有更糟糕的,但是我想不到了)

    有1000个点,1e6条边的权值都为1(题目的m最大才1e5,不过没关系,稍微糟糕一点)

    那么就意味着,每次遍历完点都没有发现可以无花费就加入的点,那也就n2 级别的复杂度,可以过。

    (为什么这样的题我要写这么多字啊。。。)

    代码

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <cmath>
    #include <vector>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5 + 10;
    vector<int>mp[maxn];
    int qu[maxn*10];
    int n,m,num[maxn];
    int main(){
        while(scanf("%d%d",&n,&m) != EOF){
            int u,v,now = 0;
            for(int i = 1;i <= n;i++)
                mp[i].clear();
            memset(num,0,sizeof(num));
            for(int i = 1;i <= m;i++){
                scanf("%d%d",&u,&v);
                mp[u].push_back(v);
                mp[v].push_back(u);
            }
    
            now = 1;
            for(int i = 0;i < mp[1].size();i++){
                v = mp[1][i];
                num[v] = 1;
            }
    
            int ans = 0,l = 0,r = 0,_l,_r,flag;
            for(int i = 2;i <= n;i++)
                qu[r++] = i;
            flag = 0;
            while(l < r){
                _r = r;
                flag = 0;
                while(l < _r){
                    u = qu[l++];
                    if(num[u] < now){
                        flag = 1;
                        now++;
                        for(int j = 0;j < mp[u].size();j++){
                            v = mp[u][j];
                            num[v]++;
                        }
                    }
                    else{
                        qu[r++] = u;
                    }
                }
                if(!flag){
                    ans++;
                    now++;
                    u = qu[l++];
                    for(int i = 0;i < mp[u].size();i++){
                        v = mp[u][i];
                        num[v]++;
                    }
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    练习四十:数组逆向输出
    练习三十九:数组插入排序
    Java awt组件间的继承关系
    java ArrayList
    java Scanner中的hasNext()方法
    java中String对象的存储位置
    java初始化块执行顺序
    java二维数组
    java数组变量
    Java数组初始
  • 原文地址:https://www.cnblogs.com/InitRain/p/12514595.html
Copyright © 2011-2022 走看看