题意:给出 n n 个点, 条边的有向图,对于每个点 v v ,求 A(v) A ( v ) 表示从点 v v 出发,能到达的编号最大的点。
首先, tarjan+缩点+dp t a r j a n + 缩 点 + d p 显然是可以的:用 tarjan t a r j a n 先来缩点,把每个强联通分量中点编号最大的作为这个强联通分量的权值,然后在 dfs d f s 中进行 dp d p ,转移方程是 dp[u]=max(dp[u],dp[v]); d p [ u ] = m a x ( d p [ u ] , d p [ v ] ) ;
这里有一种非常好的方法,我们反向连边,从最大的点开始 dfs d f s ,使每个点 i i 能访问到的结点的值都是 i i 。每个点只会被访问一次,此时的值是最优的,因为之后如果再访问到这个结点那么答案肯定没当前大了。
#include<bits/stdc++.h>
using namespace std;
struct node
{
int next,to;
}e[1001000];
int num,head[1001000],g[1001000],n,m;
void add(int from,int to)
{
e[++num].next=head[from];
e[num].to=to;
head[from]=num;
}
void dfs(int x,int d)
{
if(g[x])
return;
g[x]=d;
for(int i=head[x];i;i=e[i].next)
dfs(e[i].to,d);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
add(v,u);
}
for(int i=n;i>=1;--i)
dfs(i,i);
for(int i=1;i<=n;++i)
cout<<g[i]<<" ";
return 0;
}