There are many ways to do this problem.
I'll just mention one here
It's the Archmage.
Reverse edge building can be used, starting from the largest point dfs
We consider that every time we start from the largest point of the remaining point, we call it i temporarily, and the largest point that can be reached by this point is i.
When traversing, follow the order of n -- > 1
Because it is traversal from large to small, the first i that is encountered by each point must be the most reachable point of this point
The code is as follows
#include<iostream> #define maxx 500010 using namespace std; int n,m; struct pp { int next,to; } edge[maxx]; int cnt; int head[maxx]; int a[maxx];//Store answers void add(int u,int v) { //Adjacency list edge[++cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt; } void dfs(int x,int k) { if(a[x]) return ; //Handling rings while preserving optimal solutions a[x]=k; for(int i=head[x]; i; i=edge[i].next)//Traverse the reachable points dfs(edge[i].to,k); } inline void init() { for(int i=1; i<=n; i++) head[i]=-1; } int main() { cin>>n>>m; init(); //Initialization for(int i=1; i<=m; i++) { int u,v; cin>>u>>v; add(v,u); //Reverse side construction } for(int i=n; i>=1; i--) dfs(i,i); Recursively searching for(int i=1; i<=n; i++) cout<<a[i]<<' '; }
At the same time, you can use vector to make the code easier to read. The variables are the same as above
#include<iostream> #include<vector> #define maxx 500100 using namespace std; int n,m; vector<int > edge[maxx]; int a[maxx]; void dfs(int x,int k) { if(a[x]) return ; a[x]=k; for(int i=0; i<edge[x].size(); i++) dfs(edge[x][i],k); } int main() { cin>>n>>m; for(int i=1; i<=m; i++) { int u,v; cin>>u>>v; edge[v].push_back(u); } for(int i=n; i>=1; i--) dfs(i,i); for(int i=1; i<=n; i++) cout<<a[i]<<' '; }