POJ 3352 浅谈边双连通分量缩点

来源:互联网 发布:外链网站源码 编辑:程序博客网 时间:2024/05/18 01:20

这里写图片描述
世界真的很大
刚刚才刷了一道边双连通的Tarjan
感觉不够,迅速再敲一道练手
然后1A,哇哇哇哇
虽然是一道水题,但我自己不会说出来233

看题先:

description:

给定图G,求最少加多少边可以成为双连通图。

input:

The first line of input will consist of positive integers n and r, separated by a space, where 3 ≤ n ≤ 1000 is the number of tourist attractions on the island, and 2 ≤ r ≤ 1000 is the number of roads. The tourist attractions are conveniently labelled from 1 to n. Each of the following r lines will consist of two integers, v and w, separated by a space, indicating that a road exists between the attractions labelled v and w. Note that you may travel in either direction down each road, and any pair of tourist attractions will have at most one road directly between them. Also, you are assured that in the current configuration, it is possible to travel between any two tourist attractions.

output:

One line, consisting of an integer, which gives the minimum number of roads that we need to add.

此题题目巨长,话说POJ不是一向如此吗?
英语差的我啊,只得找翻译
一翻译,题解就出来了。。。
没什么好说的,主要还是练板子
求一个双连通分量,然后缩点,由于每一个点必定属于一个边双连通分量,所以最后一定是一棵树
然后就树的子节点+1再除2了

完整代码:

#include<stdio.h>#include<stack>#include<algorithm>using namespace std;struct edge{    int u,v,last;}ed[100010];stack <int> stk;int n,m,ans=0,num=1,idx=0,cnt=0;int head[100010],dfn[100010],low[100010],place[100010];int fa[100010],du[100010],U[100010],V[100010];void add(int u,int v){    num++;    ed[num].u=u;    ed[num].v=v;    ed[num].last=head[u];    head[u]=num;}void tarjan(int u){    dfn[u]=low[u]=++idx;    stk.push(u);    for(int i=head[u];i;i=ed[i].last)    {        if(i==(fa[u]^1)) continue ;        int v=ed[i].v;        if(!dfn[v])        {            fa[v]=i;            tarjan(v);            low[u]=min(low[u],low[v]);        }        else            low[u]=min(low[u],dfn[v]);    }    if(dfn[u]==low[u])    {        cnt++;int t=-1;        while(t!=u)        {            t=stk.top();            place[t]=cnt;            stk.pop();        }    }}void ReBuild(){    for(int i=1;i<=m;i++)    {        int u=U[i],v=V[i];        if(place[u]!=place[v])            du[place[u]]++,du[place[v]]++;    }    for(int i=1;i<=cnt;i++)        if(du[i]==1) ans++;    ans=(ans+1)/2;}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++)    {        int u,v;        scanf("%d%d",&u,&v);        add(u,v),add(v,u);          U[i]=u,V[i]=v;    }    for(int i=1;i<=n;i++)        if(!dfn[i]) tarjan(i);    ReBuild();    printf("%d\n",ans);    return 0;}/*Whoso pulleth out this sword from this stone and anvil is duly born King of all England*/

嗯,就是这样

原创粉丝点击