(Day5)算法复健运动for蓝桥杯-拓扑+前向星存储+DFS+记忆化

(Day5)算法复健运动for蓝桥杯-拓扑+前向星存储+DFS+记忆化

https://www.luogu.com.cn/problem/P1137

这题比较简单,但是比较经典,看了下我几年前的写法是用拓扑排序写的,图的存储方法用的是前向星。而现在我已经忘记前向星怎么存储的了,而且一看到这种需要继承深度的题目脑子里只有dfs。

1. DFS写法+vector存储

所以我先用vector存储和dfs写了一遍,因为如果说这个地方搜过了,就直接返回不再dfs了,所以用上了记忆化。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+9;
vector<int>ve[N];
int r[N];
int deep[N];
int dfs(int x)
{
    for(int i = 0; i < ve[x].size(); i ++)
    {
        if(deep[ve[x][i]] == 1)//如果=1说明没有搜过
        deep[x] = max(dfs(ve[x][i]) + 1, deep[x]);//继承深度最高的那一个
        else deep[x] = max(deep[ve[x][i]] + 1, deep[x]);
    }
    return deep[x];
}
int main()
{
    int n, m, x, y;
    cin>>n>>m;
    for(int i = 1; i <= n; i ++)
    {
        deep[i]=1;
    }
    while(m --)
    {
        cin>>x>>y;
        ve[y].push_back(x);//反着计算
        r[x] ++;//计算入度
    }
    for(int i = 1; i <= n; i ++)
    {
        if(r[i] == 0) dfs(i);//从入度为0的开始搜
    }
    for(int i = 1; i <= n; i ++)
    {
        cout<<deep[i]<<endl;
    }
    return 0;
}

2.常规的拓扑(TLE)

但是这个数据结构不是一棵树,更合理的方法是使用拓扑排序写,这里换一个存储方法,复习一下前向星的存储方法。

#include<bits/stdc++.h>
using namespace std;
const int N= 1e5+9;
struct node
{
    int t,net;
}e[2*N];
int head[N];//如果说编号是从0开始需要全部置为-1
int tot=1;//边的编号
int deep[N],r[N];
void add(int x,int y)
{
    e[tot].t = y;//边到的地方
    e[tot].net = head[x];//同样x的上一个边的编号
    head[x] = tot++;//设为当前边
}
int main()
{
    int n,m,x,y;
    cin>>n>>m;
    while(m--)
    {
        cin>>x>>y;
        add(x,y);
        r[y]++;
    }
    for(int i=1;i<=n;i++)deep[i]=1;
    while(1)
    {
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            if(r[i]!=0)continue;
            sum++;
            r[i]=-1;
            for(int j=head[i];j;j=e[j].net)//如果说编号从0开始,这个j要变成j!=-1
            {
                r[e[j].t]--;
                deep[e[j].t]=max(deep[i]+1,deep[e[j].t]);
            }
        }
        if(sum==0)break;
    }
    for(int i=1;i<=n;i++)
    {
        cout<<deep[i]<<endl;
    }
    return 0;
}

3.时间优化版

利用队列,如果说一个点的入度减小为0,就加入队列

#include<bits/stdc++.h>
using namespace std;
const int N= 1e5+9;
struct node
{
    int t,net;
}e[2*N];
int head[N];
int tot=1;
int deep[N],r[N];
queue<int>qu;
void add(int x,int y)
{
    e[tot].t = y;
    e[tot].net = head[x];
    head[x] = tot++;
}
void bfs()
{
    while(!qu.empty())
    {
        int x = qu.front();
        qu.pop();
        for(int i = head[x];i;i=e[i].net)//因为序号从1开始所以第二个是i
        {
            int to = e[i].t;
            deep[to]=max(deep[x]+1,deep[to]);
            r[to]--;
            if(r[to]==0)qu.push(to);
        }
    }
}
int main()
{
    int n,m,x,y;
    cin>>n>>m;
    while(m--)
    {
        cin>>x>>y;
        add(x,y);
        r[y]++;
    }
    for(int i=1;i<=n;i++)
    {
        deep[i]=1;
        if(r[i]==0)qu.push(i);
    }
    bfs();
    for(int i=1;i<=n;i++)
    {
        cout<<deep[i]<<endl;
    }
    return 0;
}

4.带权的前向星存储

int head[N];
struct node
{
    int t,net,w;
}a[2*N];
int tot = 1;
void add(int x,int y,int w)
{
    a[tot].t=y;
    a[tot].w=w;
    a[tot].net=head[x];
    head[x]=tot++;
}
posted @   wlqtc  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示