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

 

posted @ 2022-05-28 13:32  董晓  阅读(817)  评论(1编辑  收藏  举报