zoukankan      html  css  js  c++  java
  • BZOJ 1098 [POI2007]办公楼biu(反向图bfs+并查集优化)

    【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=1098

    【题目大意】

      现在有一张图,要求将这张图的点划分为尽量多的分组,对于不同分组的两个点
      要求必须存在连边。

    【题解】

      不同分组之间的两点必须连边等价于没有连边的点一定在同一分组内,
      所以题目转化为求反图的连通块和其大小,搜索的理论复杂度O(n^2),显然不行,
      bfs的时候对于已经归入其余连通块的点用并查集进行段无效信息处理,减少搜索树的分支,
      显然经过这样的处理搜索分支的数量下降得非常快,就能顺利解决此题了。

    【代码】

    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <queue>
    using namespace std;
    const int N=100010;
    int f[N],n,m,vis[N],ans,cnt[N];
    vector<int> v[N];
    int sf(int x){return f[x]==x?x:f[x]=sf(f[x]);}
    void bfs(int st){
        queue<int> q;
        q.push(st);
        cnt[++ans]=1;
        while(q.size()){
            int x=q.front();q.pop();f[x]=sf(x+1);
            for(int i=0;i<v[x].size();i++)vis[v[x][i]]=x;
            for(int i=sf(1);i<=n;i=sf(i+1))if(vis[i]!=x){
                cnt[ans]++;
                f[i]=sf(i+1);
                q.push(i);
            }
        }
    }
    int main(){
        while(~scanf("%d%d",&n,&m)){
            ans=0;
            while(m--){
                int x,y;
                scanf("%d%d",&x,&y);
                v[x].push_back(y);
                v[y].push_back(x);
            }
            for(int i=1;i<=n+1;i++)f[i]=i;
            for(int i=1;i<=n;i=sf(i+1))bfs(i);
            printf("%d
    ",ans);
            sort(cnt+1,cnt+ans+1);
            for(int i=1;i<=ans;i++)printf("%d ",cnt[i]);
            puts("");
        }return 0;
    }
  • 相关阅读:
    [uboot] (番外篇)uboot relocation介绍(转)
    [uboot] (番外篇)global_data介绍(转)
    [uboot] (第三章)uboot流程——uboot-spl代码流程 后续2018版本分析
    AddressUtils
    ruoyi HttpUtils
    ruoyi IpUtils
    ruoyi StringUtils
    JSONObject
    jackson解析处理JSON
    spring boot pom demo
  • 原文地址:https://www.cnblogs.com/forever97/p/bzoj1098.html
Copyright © 2011-2022 走看看