P3916 图的遍历(Tarjan缩点和反向建边)

P3916 图的遍历 - 洛谷 | 计算机科学教育新生态

写法一:Tarjan

思路:先运用Tarjan算法得到每个连通块中最大的编号,然后对每个连通块进行缩点重新建图,进行dfs,得到缩点后的连通块能够达到的最大编号。

Code:

cpp 复制代码
constexpr int N=1e5+5,mod=1e9+7;

int a[N],dfn[N],stk[N],low[N],top,scc[N],cnt,tot;
int n,m,instack[N],ma[N],sz[N];
bool st[N];
int x[N],y[N];
vector<int> e[N],g[N];

void Tarjan(int u)
{
    stk[++top]=u,instack[u]=1;
    low[u]=dfn[u]=++tot;
    for(auto t:e[u])
    {
        if(!dfn[t])
        {
            Tarjan(t);
            low[u]=min(low[u],low[t]);
        }
        else if(instack[t]) low[u]=min(low[u],dfn[t]);
    }

    if(low[u]==dfn[u])
    {
       
       cnt++; int y;
        //cout<<"____"<<cnt<<' '<<u<<endl;
       do{
         y=stk[top--]; instack[y]=0;
        scc[y]=cnt;
          // cout<<"____"<<cnt<<' '<<y<<endl;
        ma[cnt]=max(ma[cnt],y);
       }while(u!=y);
    }
}

void dfs(int u)
{
    if(a[u]) return ;
    a[u]=ma[u];
   // cout<<u<<' '<<a[u]<<' '<<g[u].size()<<endl;
    for(auto t:g[u])
    {
        if(!a[t])
        {
          dfs(t);
        }
        a[u]=max(a[u],a[t]);
       // cout<<u<<' '<<t<<' '<<a[u]<<endl;
    }
}
void solve()
{
   cin>>n>>m;
   for(int i=0;i<m;i++)
   {
    cin>>x[i]>>y[i];
    e[x[i]].push_back(y[i]);
   }

   for(int i=1;i<=n;i++)
       if(!dfn[i])
        Tarjan(i);
    for(int i=0;i<m;i++)
    {
        if(scc[x[i]]==scc[y[i]]) continue;
        g[scc[x[i]]].push_back(scc[y[i]]);
    }
    for(int i=1;i<=cnt;i++)
    {
        if(!a[i]) dfs(i);
    }
    for(int i=1;i<=n;i++)
        cout<<a[scc[i]]<<' ';
}

写法二:反向建图

既然要计算每个点能走到的最大编号,我们可以直接从大编号 开始搜索与它关联的路径,该路径上的点均为大编号。

Code:

cpp 复制代码
constexpr int N=1e5+5,mod=1e9+7;

int a[N],n,m;
vector<int> e[N];

void dfs(int u,int i)
{
    if(a[u]) return ;
   a[u]=i;
   for(auto t:e[u])
   {
    if(!a[t])
    {
        dfs(t,i);
    }
   }

}
void solve()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int a,b;cin>>a>>b;
        e[b].push_back(a);
    }
    for(int i=n;i;i--)
     if(!a[i]) dfs(i,i);
 for(int i=1;i<=n;i++) cout<<a[i]<<' ';
}
相关推荐
好易学·数据结构1 天前
可视化图解算法75:最长上升子序列(最长递增子序列)
数据结构·算法·leetcode·动态规划·力扣·牛客网
Jeremy爱编码1 天前
leetcode热题岛屿数量
算法·leetcode·职场和发展
闻缺陷则喜何志丹1 天前
【组合数学 动态规划】P6870 [COCI2019-2020#5] Zapina|普及+
c++·数学·算法·动态规划·组合数学
zl_vslam1 天前
SLAM中的非线性优-3D图优化之相对位姿Between Factor-SO3/t形式(十一)
人工智能·算法·计算机视觉·3d
CoderCodingNo1 天前
【GESP】C++五级真题(贪心考点) luogu-B3872 [GESP202309 五级] 巧夺大奖
开发语言·c++
唐·柯里昂7981 天前
[rk3566AI模型部署]泰山派buildroot部署yolov5 使用rknn_model_zoo
c语言·c++·笔记·yolo·rk3566·瑞芯微·泰山派
图形学爱好者_Wu1 天前
每日一个C++知识点|const和static的区别
c++
aini_lovee1 天前
基于 OpenCV 的模板匹配算法的 C 语言实现
c语言·opencv·算法
core5121 天前
EM 算法 (期望最大化):在迷雾中寻找真相
算法·em·期望最大化
CoovallyAIHub1 天前
YOLO11-4K:面向4K全景图像的高效实时检测框架,CVIP360数据集开源
深度学习·算法·计算机视觉