• 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;
    }
  • 相关阅读:
    FIS3常用配置
    PC端模拟移动端访问 字体大小限制
    table布局 防止table变形 td固定宽度
    fis3 scss 版本报错
    移动端布局方案 网易
    提示浏览器版本低
    JS Math.round()方法原理
    margin 负边距应用
    box-shadow IE8兼容处理
    border-radius IE8兼容处理
  • 原文地址:https://www.cnblogs.com/forever97/p/bzoj1098.html
Copyright © 2020-2023  润新知