洛谷 P3916图的遍历
题意:
对于有向图的每个点 v,求从点 v 出发,能到达的编号最大的点。
思路:
如果从每个点出发搜索,显然复杂度过于高昂。考虑建反图(也就是,把原图中所有边的方向反过来),从大到小遍历点,依次出发,寻找能被其覆盖的其他点,并为这些点作标记。如果当前搜索到的点已经被之前遍历的更大的点标记了,则可立即回溯(相当于记忆化搜索)。
如记忆化搜索一样,总时间复杂度为\(O(n+m)\)。
代码:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn=1e5+5;
vector<int> G[maxn];
int tag[maxn];
void dfs(int x, int now)
{
if(tag[x]) return;
tag[x]=now;
for(int i:G[x])
dfs(i,now);
}
int main()
{
cin.tie(0)->sync_with_stdio(false);
int n,m;
cin>>n>>m;
for(int i=1;i<=m;++i)
{
int x,y;
cin>>x>>y;
G[y].push_back(x);
}
for(int i=n;i>0;--i)
dfs(i,i);
for(int i=1;i<=n;++i)
cout<<tag[i]<<" ";
}

浙公网安备 33010602011771号