Doves and bombs UVA - 10765

Doves and bombs UVA - 10765

图论·双连通分量

题目大意:

给定一个n个点的连通的无向图,一个点的“鸽子值”定义为将它从图中删去后连通块的个数。求每个点的“鸽子值”。

题解:

就是求一个点包含在几个双连通分量里。
其实不用求出双联通分量,只要在dfs的时候碰到low[v]>=dfn[u]的时候统计一下答案即可。

Code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 50005;

struct Edge{ int to,next; }e[N*2];
int head[N], ec;
void clearEdge(){ memset(head,0,sizeof(head)); ec=0; }
void add(int a,int b){ ec++; e[ec].to=b; e[ec].next=head[a]; head[a]=ec; }

struct Ans{
    int id,val;
    bool operator < (const Ans & tp) const { 
        return val > tp.val || (val==tp.val && id<tp.id); 
    }
}ans[N];

int low[N],dfn[N],tim;
int n,m;

void clear(){
    clearEdge();
    for(int i=1;i<=n;i++) ans[i].id=i, ans[i].val=1;
    tim=0; memset(dfn,0,sizeof(dfn));
}

void dfs(int u,int f){
    low[u]=dfn[u]=++tim; int child=0;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(!dfn[v]){
            child++;
            dfs(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u]) ans[u].val++;
        }
        else if(dfn[v]<dfn[u] && v!=f) 
            low[u]=min(low[u],dfn[v]);
    }
    if(f<0 && child==1) ans[u].val=1;
}

int main(){
    freopen("a.in","r",stdin);
    while(~scanf("%d%d",&n,&m) && (n||m)){
        int a,b;
        clear();
        while(~scanf("%d%d",&a,&b) && a>=0){
            a++; b++;
            add(a,b); add(b,a);
        }
        dfs(1,-1);
        sort(ans+1,ans+1+n);
        for(int i=1;i<=m;i++){
            printf("%d %d\n",ans[i].id-1,ans[i].val);
        }
        puts("");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值