Doves and bombs UVA

来源:互联网 发布:文字复制软件 编辑:程序博客网 时间:2024/06/05 11:46

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("");    }}