洛谷图的遍历 P3916
题目描述
给出NN个点,MM条边的有向图,对于每个点vv,求A(v)A(v)表示从点vv出发,能到达的编号最大的点。
输入格式
第1 行,2 个整数N,MN,M。
接下来MM行,每行2个整数U_i,V_iUi,Vi,表示边(U_i,V_i)(Ui,Vi)。点用1, 2,\cdots,N1,2,⋯,N编号。
输出格式
N 个整数A(1),A(2),\cdots,A(N)A(1),A(2),⋯,A(N)。
输入输出样例
输入 #1复制
4 3 1 2 2 4 4 3
输出 #1复制
4 4 3 4
说明/提示
• 对于60% 的数据,1 \le N . M \le 10^31≤N.M≤103;
• 对于100% 的数据,1 \le N , M \le 10^51≤N,M≤105。
description:
n个点m条边,每个点能到最大编号的点是多少
solution:
从n个点开始 每个点都dfs肯定超时 , 正难则反,我们反过来想,建立一个反边,从1个点到n个点,变成n个点到1个点,从大的点开始dfs,更新每个点到的编号最大值, 如果当前点已经到过,就直接返回,因为从大到小更新,已经更新的肯定是更大的
code:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 50;
vector<int> e[N];
int n, m;
bool vis[N];
int res[N];
void dfs(int x, int dep) {
if(res[x]){
return ;
}
res[x] = dep;
for(int i = 0;i < e[x].size();i ++){
int to = e[x][i];
dfs(to,dep);
}
}
int main() {
cin >> n >> m;
while (m--) {
int u, v;
cin >> u >> v;
e[v].push_back(u);
}
for (int i = n; i >= 1; i --) {
dfs(i, i);
}
for(int i = 1;i <= n;i ++){
cout << res[i] << ' ';
}
return 0;
}