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]<<' ';
}
相关推荐
科大饭桶34 分钟前
数据结构自学Day5--链表知识总结
数据结构·算法·leetcode·链表·c
小高Baby@35 分钟前
map数据结构在Golang中是无序的,并且键值对的查找效率较高的原因
数据结构
北风toto35 分钟前
python学习DataFrame数据结构
数据结构·python·学习
mit6.8241 小时前
[Meetily后端框架] Whisper转录服务器 | 后端服务管理脚本
c++·人工智能·后端·python
L_autinue_Star2 小时前
手写vector容器:C++模板实战指南(从0到1掌握泛型编程)
java·c语言·开发语言·c++·学习·stl
我爱C编程3 小时前
基于Qlearning强化学习的1DoF机械臂运动控制系统matlab仿真
算法
chao_7893 小时前
CSS表达式——下篇【selenium】
css·python·selenium·算法
chao_7893 小时前
Selenium 自动化实战技巧【selenium】
自动化测试·selenium·算法·自动化
YuTaoShao3 小时前
【LeetCode 热题 100】24. 两两交换链表中的节点——(解法一)迭代+哨兵
java·算法·leetcode·链表
怀旧,3 小时前
【数据结构】8. 二叉树
c语言·数据结构·算法