图的遍历
P3916 图的遍历
题目描述
给出 \(N\) 个点,\(M\) 条边的有向图,对于每个点 \(v\),求 \(A(v)\) 表示从点 \(v\) 出发,能到达的编号最大的点。
输入格式
第 \(1\) 行 \(2\) 个整数 \(N,M\),表示点数和边数。
接下来 \(M\) 行,每行 \(2\) 个整数 \(U_i,V_i\),表示边 \((U_i,V_i)\)。点用 \(1,2,\dots,N\) 编号。
输出格式
一行 \(N\) 个整数 \(A(1),A(2),\dots,A(N)\)。
输入输出样例 #1
输入 #1
4 3
1 2
2 4
4 3
输出 #1
4 4 3 4
说明/提示
- 对于 \(60\%\) 的数据,\(1 \leq N,M \leq 10^3\)。
- 对于 \(100\%\) 的数据,\(1 \leq N,M \leq 10^5\)。
这道题问一个点能走到的最大的点是多少,我们可以反向建边,求一个点最大可以由哪个点走到
#include<iostream>
#include<vector>
using namespace std;
const int N=1e5+5;
vector<int>v[N];
int d[N];
void dfs(int x,int y){
d[x]=y;
for(int i=0;i<v[x].size();i++){
if(!d[v[x][i]])dfs(v[x][i],y);//没有被更新才能递归,如果不是零,说明被之前更大的点更新了
}
}
int main(){
int n,m;
cin>>n>>m;
while(m--){
int x,y;
cin>>x>>y;
v[y].push_back(x);
}
for(int i=n;i>=1;i--){
if(!d[i])dfs(i,i);//由于是从大到小遍历,如果没有比他更大的点走到,那么最大的点肯定是他本身;
}
for(int i=1;i<=n;i++)cout<<d[i]<<" ";
return 0;
}

浙公网安备 33010602011771号