码迷,mamicode.com
首页 > 其他好文 > 详细

cf 1243 D. 0-1 MST(队列瞎搞)

时间:2020-03-17 23:51:51      阅读:73      评论:0      收藏:0      [点我收藏+]

标签:题意   stream   printf   ring   技术   nbsp   memset   scanf   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\n",ans);
    }
    return 0;
}
View Code

 

cf 1243 D. 0-1 MST(队列瞎搞)

标签:题意   stream   printf   ring   技术   nbsp   memset   scanf   mst   

原文地址:https://www.cnblogs.com/InitRain/p/12514595.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!