(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++;
}
分类:
ACM
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现