zoukankan      html  css  js  c++  java
  • Uva 10765 鸽子和炸弹

    题目链接:https://vjudge.net/contest/166461#problem/B

    题意:

    给一个无向图,求每一个点删除后,剩下的连通块的数目;

    分析:

    只有割顶被删掉后,连通分量才会改变,改变多少呢? 就是他这个割顶除 父亲结点,的其他孩子结点(及其子孙结点)是否返回到最早的祖先结点(lowv) <= low[u];再加上原图的连通块;

    WA了很多次,错误地方有两个;

    1、板子抄错了,low 函数没有用子孙结点更新;

    2、即时不是割顶,也要加入结果中,就当是他删掉后,连通分量没有改变;

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int maxn = 10000+5;
    int n,m;
    
    bool cmp(pair<int,int> a,pair<int,int> b) {
        if(a.second == b.second)
            return a.first < b.first;
        return a.second > b.second;
    }
    
    struct Sol {
        int pre[maxn],iscut[maxn],dfs_clock,bcc_cnt,low[maxn];
        vector<int> G[maxn];
        vector<pair<int,int> > ans;
    
        void init(int n) {
            for(int i=0;i<=n;i++)
                G[i].clear();
            ans.clear();
        }
    
        void AddEdge(int from,int to) {
            G[from].push_back(to);
            G[to].push_back(from);
        }
    
        int dfs(int u,int fa) {
            int lowu = pre[u] = ++dfs_clock;
            int child = 0,num = 0;
            for(int i=0; i<G[u].size(); i++) {
                int v = G[u][i];
                if(v==fa) continue;
                if(!pre[v]) {
                    child++;
                    int lowv = dfs(v,u);
                    lowu = min(lowu,lowv);
                    if(lowv>=pre[u]) {
                        iscut[u] = true;
                        num++;
                    }
                } else if(pre[v]<pre[u]) {
                    lowu = min(lowu,pre[v]);
                }
            }
            if(fa<0&&child==1) {
                iscut[u] = 0;
                num = 0;
            }
            //if(iscut[u])
            ans.push_back(make_pair(u,num));
            low[u] = lowu;
            return lowu;
        }
    
        void find_bcc(int n) {
            memset(pre,0,sizeof(pre));
            memset(iscut,0,sizeof(iscut));
            memset(low,0,sizeof(low));
            dfs_clock = bcc_cnt = 0;
            for(int i=0; i<n; i++)
                if(!pre[i]) {
                    bcc_cnt++;
                    dfs(i,-1);
                }
        }
    
        void print_ans() {
            sort(ans.begin(),ans.end(),cmp);
            for(int i=0; i<m; i++)
                printf("%d %d
    ",ans[i].first,ans[i].second+bcc_cnt);
            puts("");
        }
    } sol;
    
    int main() {
        while(scanf("%d%d",&n,&m),n) {
            sol.init(n);
            int u,v;
            while(true) {
                scanf("%d%d",&u,&v);
                if(u==-1) break;
                sol.AddEdge(u,v);
            }
            sol.find_bcc(n);
            sol.print_ans();
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    【网络公开课总结】砸蛋中奖效果
    【网络收集】如何修改vs tfs的登录名和密码 .
    在rdlc 中 显示成 yyyy年MM月dd日
    sql 将某一列的值拼接成字符串
    【网络收集】获取JavaScript 的时间使用内置的Date函数完成
    处理传递过来的拼接的值,中间用逗号相隔
    行列转换 pivot
    【网络收集】存储过程中自动生成主键
    Java多线程基础知识整理二
    Java多线程基础知识整理
  • 原文地址:https://www.cnblogs.com/TreeDream/p/6952476.html
Copyright © 2011-2022 走看看