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
原文地址:https://www.cnblogs.com/TreeDream/p/6952476.html