D18 Tarjan eDCC 缩点
视频链接:https://www.bilibili.com/video/BV1MA4y1d7CM
// POJ 3177 #include <cstring> #include <iostream> #include <algorithm> #include <stack> using namespace std; const int N=5010,M=20010; int n,m,a,b; struct edge{int v,ne;}e[M]; int h[N],idx=1;//2,3开始配对 int dfn[N],low[N],tot; stack<int> stk; int dcc[N],cnt; int bri[M],d[N]; void add(int a,int b){ e[++idx].v=b; e[idx].ne=h[a]; h[a]=idx; } void tarjan(int x,int in_edg){ dfn[x]=low[x]=++tot; stk.push(x); for(int i=h[x];i;i=e[i].ne){ int y=e[i].v; if(!dfn[y]){//若y尚未访问 tarjan(y,i); low[x]=min(low[x],low[y]); if(low[y]>dfn[x]) bri[i]=bri[i^1]=true; } else if(i!=(in_edg^1))//不是反边 low[x]=min(low[x],dfn[y]); } if(dfn[x]==low[x]){ ++cnt; while(1){ int y=stk.top();stk.pop(); dcc[y]=cnt;//记录eDCC if(y==x)break; } } } int main(){ cin>>n>>m; while(m--){ cin>>a>>b; add(a,b),add(b,a); } tarjan(1,0); for(int i=2;i<=idx;i++) if(bri[i]) d[dcc[e[i].v]]++;//度数 int sum=0; for(int i=1;i<=cnt;i++) if(d[i]==1) sum++;//叶节点数 printf("%d\n",(sum+1)/2); return 0; }