D18 Tarjan eDCC 缩点

视频链接:https://www.bilibili.com/video/BV1MA4y1d7CM

 

 

 

P2860 [USACO06JAN] Redundant Paths G - 洛谷 | 计算机科学教育新生态

POJ 3177 -- Redundant Paths

复制代码
// Tarjan eDCC缩点 O(n)
#include <cstring>
#include <iostream>
#include <algorithm>
#include <stack>
using namespace std;

const int N=5010,M=20010;
int n,m,x,y,sum=0;
int head[N],idx=1; //2,3开始配对
struct E{int to,ne;}e[M];
int dfn[N],low[N],tim,dcc[N],cnt,bri[M],du[N];
stack<int> s;

void add(int x,int y){
  e[++idx].to=y;e[idx].ne=head[x];head[x]=idx;
}
void tarjan(int x,int ine){
  dfn[x]=low[x]=++tim; s.push(x);
  for(int i=head[x];i;i=e[i].ne){
    int y=e[i].to;
    if(!dfn[y]){ //若y尚未访问
      tarjan(y,i);
      low[x]=min(low[x],low[y]);
      if(dfn[x]<low[y])
        bri[i]=bri[i^1]=1; //
    }
    else if(i!=(ine^1)) //不是反边
      low[x]=min(low[x],dfn[y]);
  }
  if(dfn[x]==low[x]){
    ++cnt;
    while(1){
      int y=s.top();s.pop();
      dcc[y]=cnt; //eDCC
      if(y==x)break;
    }
  }
}
int main(){
  cin>>n>>m;
  while(m--){
    cin>>x>>y; add(x,y),add(y,x);
  }
  tarjan(1,0);
  for(int i=2;i<=idx;i++)
    if(bri[i]) du[dcc[e[i].to]]++; //度数
  for(int i=1;i<=cnt;i++)
    if(du[i]==1) sum++; //叶节点数
  printf("%d\n",(sum+1)/2);
  return 0;
}
复制代码

 

复制代码
// Tarjan eDCC缩点 O(n)
#include <cstring>
#include <iostream>
#include <algorithm>
#include <stack>
using namespace std;

const int N=5010,M=20010;
int n,m,u[N],v[N],sum=0;
int head[N],idx=1; //2,3开始配对
struct E{int to,ne;}e[M];
int dfn[N],low[N],tim,dcc[N],cnt,vis[M],du[N];
stack<int> s;

void add(int x,int y){
  e[++idx].to=y;e[idx].ne=head[x];head[x]=idx;
}
void tarjan(int x){
  dfn[x]=low[x]=++tim; s.push(x);
  for(int i=head[x];i;i=e[i].ne)
    if(!vis[i]){
      vis[i]=vis[i^1]=1; //标记反边
      int y=e[i].to;
      if(!dfn[y]){ //若y尚未访问
        tarjan(y);
        low[x]=min(low[x],low[y]);
      }
      else low[x]=min(low[x],dfn[y]);
    }
  if(dfn[x]==low[x]){
    ++cnt;
    while(1){
      int y=s.top(); s.pop();
      dcc[y]=cnt; //eDCC
      if(y==x)break;
    }
  }
}
int main(){
  cin>>n>>m;
  for(int i=1;i<=m;i++){
    cin>>u[i]>>v[i]; add(u[i],v[i]),add(v[i],u[i]);
  }
  tarjan(1);
  for(int i=1;i<=m;i++)
    if(dcc[u[i]]!=dcc[v[i]])
      du[dcc[u[i]]]++,du[dcc[v[i]]]++; //度数
  for(int i=1;i<=cnt;i++)
    if(du[i]==1) sum++; //叶节点数
  printf("%d\n",sum+1>>1);
  return 0;
}
复制代码

 

P8436 【模板】边双连通分量 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

 

posted @   董晓  阅读(961)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验
点击右上角即可分享
微信分享提示