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;}