冗余路径Redundant Paths
tarjan 割点
#include<cstdio> #include<cstring> #include<algorithm> #include<stack> using namespace std; const int maxn=5010; const int maxm=20010; int n,m,u[maxn],v[maxn],x,y,cur,h[maxn],nxt[maxm],p[maxm],index_,dfn[maxn],low[maxn],bcc[maxn],deg[maxn],ans,ltt; bool tf[maxm]; stack<int>st; inline void add_edge(int x,int y) { cur++; nxt[cur]=h[x]; h[x]=cur; p[cur]=y; } void dfs(int cur) { dfn[cur]=low[cur]=++index_; for(int j=h[cur];j!=-1;j=nxt[j])if(tf[j]) { int i=p[j]; if(dfn[i])low[cur]=min(low[cur],dfn[i]); else { st.push(i); tf[j]=tf[(j&1)?j+1:j-1]=false; dfs(i); tf[j]=tf[(j&1)?j+1:j-1]=true; low[cur]=min(low[cur],low[i]); } } if(dfn[cur]==low[cur]) { ans++; while(!st.empty()) { bcc[st.top()]=ans; if(st.top()==cur){st.pop();break;} st.pop(); } } } int main() { memset(h,-1,sizeof h); memset(tf,true,sizeof tf); scanf("%d%d",&n,&m); for(int i=0;i<m;i++)scanf("%d%d",u+i,v+i),add_edge(u[i],v[i]),add_edge(v[i],u[i]); for(int i=1;i<=n;i++)if(!dfn[i])ans=0,st.push(i),dfs(i); for(int i=0;i<m;i++)if(bcc[u[i]]!=bcc[v[i]])deg[bcc[u[i]]]++,deg[bcc[v[i]]]++; for(int i=1;i<=n;i++)if(deg[i]==1)ltt++; printf("%d\n",(ltt+1)/2); return 0; }