洛谷 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]<<" ";
}
posted @ 2023-01-02 10:25  ice_dragon_grass  阅读(129)  评论(0)    收藏  举报