题目链接:https://www.luogu.com.cn/problem/P3916
解题思路
看到题解区有dalao用的Tarjan算法,然而我并没有学过。就想用DFS做,然而感觉不太好操作的样子。最后看到dalao们说要反向建图,这才恍然大悟。
如果反着建图,那么点A能到达点B就成了点B能到达点A。然后从 n 开始倒着枚举每个点,如果搜到了一个已经被其它点遍历到过的点,那么显然有一个编号更大可以走到他(即他可以遍历到一个比当前能到达的最大编号更大的点)
AC代码
#include<bits/stdc++.h>
using namespace std;
int n,m,ans[100001];
vector<int> adj[100001];
void dfs(int u,int k){
if(ans[u]) return;
ans[u]=k;
for(int i=0;i<adj[u].size();i++){
dfs(adj[u][i],k);
}
}
int main() {
scanf("%d%d",&n,&m);
int a,b;
while(m--){
scanf("%d%d",&a,&b);
adj[b].push_back(a);
}
for(int i=n;i>0;i--) dfs(i,i);
for(int i=1;i<=n;i++){
if(i!=1) printf(" ");
printf("%d",ans[i]);
}
return 0;
}