Redundant Paths poj&hoj 割边 tarjan

来源:互联网 发布:网络电视转换数字电视 编辑:程序博客网 时间:2024/05/22 00:24

/*题意就是至少加多少条边,使得任意两点间至少有两条不同的路。求双连通分量。然后统计叶子个数,即入度为1的点的个数,然后ans=(num+1)/2.在求双连通分量的过程中low值相等的是在同一个分量里。不需要用stack来进行保存。*/#include <stdio.h>#include <cstring>#include <iostream>using namespace std;const int maxm=10001;const int maxn=5001;struct edge{    int to,next;} e[maxm<<1];int n,m,cnt,t;int head[maxn],low[maxn],dfn[maxn],in[maxn];bool vis[maxn];void add(int i,int j){    e[t].to=j;    e[t].next=head[i];    head[i]=t++;}void tarjan(int u,int f){    vis[u]=true;    low[u]=dfn[u]=++cnt;    for(int i=head[u]; i!=-1; i=e[i].next)    {        int v=e[i].to;        if(f==v) continue;        if(!vis[v]) tarjan(v,u);        low[u]=min(low[u],low[v]);    }}bool judge(int a,int b){    for(int i=head[a]; i!=-1; i=e[i].next)        if(e[i].to==b) return false;    return true;}int main(){    while(scanf("%d%d",&n,&m)==2)    {        memset(head,-1,sizeof(head));        memset(e,0,sizeof(e));        memset(dfn,0,sizeof(dfn));        memset(low,0,sizeof(low));        memset(in,0,sizeof(in));        memset(vis,false,sizeof(vis));        t=cnt=0;        int u,v;        while(m--)        {            scanf("%d%d",&u,&v);            if(judge(u,v))            {                add(u,v);                add(v,u);            }        }        tarjan(1,0);        for(int i=1; i<=n; i++)        {            for(int j=head[i]; j!=-1; j=e[j].next)            {                int v=e[j].to;                if(low[i]!=low[v])                    in[low[i]]++;            }        }        int ans=0;        for(int i=1; i<=n; i++)            if(in[i]==1) ans++;        printf("%d\n",(ans+1)/2);    }    return 0;}