洛谷 P3916 图的遍历(vector存图,反向建边,dfs

洛谷 P3916 图的遍历(vector存图,反向建边,dfs
传送门戳这儿
题目描述

给出N个点,MMM条边的有向图,对于每个点v,求A(v)表示从点v出发,能到达的编号最大的点。
输入格式

第1 行,2 个整数N,M。

接下来M行,每行2个整数Ui,Vi,表示边(Ui,Vi)。点用1,2,⋯ ,N编号。
输出格式

N 个整数A(1),A(2),⋯ ,A(N)。
输入输出样例
输入 #1

4 3
1 2
2 4
4 3

输出 #1

4 4 3 4

说明/提示

• 对于60% 的数据,1≤N.M≤10^3;

• 对于100% 的数据,1≤N,M≤10^5。

题解/我的思路
图论提高题,如果按照题意从上往下建图,想要找到每一个节点联通的最大值,就必须对每一个节点dfs,显然,时间复杂度是O(N^2)会超时。
既然是找每一个节点的最大值,何不要最大值来找与他联通的节点们呢。
反向建边。
从最大的节点开始dfs找与他联通的节点,赋值并标记。

喜闻乐见的 全部代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

vector<int> vvr[100300];
int num[100300];

void dfs(int i,int m){
    if(num[i]!=0) return;
    num[i]=m;
    for(int a=1;a<=vvr[i].size();a++){
        dfs(vvr[i][a-1],m);
    }
}

int main(){
    int n,m,a,i,x,y;
    cin>>n>>m;
    for(i=1;i<=m;i++){
        cin>>x>>y;
        vvr[y].push_back(x);
    }
    for(i=n;i>=1;i--){
        dfs(i,i);
    }
    for(i=1;i<=n;i++)
        cout<<num[i]<<" ";
}

你可能感兴趣的:(洛谷 P3916 图的遍历(vector存图,反向建边,dfs)