洛谷3916 图的遍历——搜索、邻接表

题目描述

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

输入格式:

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

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

输出格式:

N 个整数 A(1),A(2),⋯,A(N)

输入样例

4 3
1 2
2 4
4 3

样例输出

4 4 3 4

本题反向建边。题目问的是每个点能够到达的最大编号的点,反过来想就是反向建边后,从当前最大编号开始遍历(搜索),能达到哪些点,哪些点的答案就应该是当前最大编号的点。

#include 
#include 
using namespace std;

const int maxn = 10010;

struct Edge{
    int to, nxt;
}edge[maxn];

int ihead[maxn];
int cnt;
int N, M;
int ans[maxn];

// 连一条从x到y的边
void add(int x, int y) {
    edge[++ cnt].nxt = ihead[x];
    edge[cnt].to = y;
    ihead[x] = cnt;
}

void dfs(int cur, int st) {
    if (ans[cur] != -1) return;
    ans[cur] = st;
    // 遍历边
    for (int i = ihead[cur]; i; i = edge[i].nxt)
        dfs(edge[i].to, st);
}

int main() {
    memset(ans, -1, sizeof ans);
    cin >> N >> M;
    for (int i = 0; i < M; i ++ ) {
        int x, y;
        cin >> x >> y;
        add(y, x);
    }
    for (int i = N; i >= 1; i -- ) dfs(i ,i);
    for (int i = 1; i <= N; i ++) cout << ans[i] << " ";
    cout << endl;

}








// 使用vector实现邻接表
#include 
#include 
#include 
using namespace std;

#define MAXL 100010

int N, M, A[MAXL];
vector<int> G[MAXL]; //vector存图 

void dfs(int x, int d) {
    if(A[x]) return; //访问过 
    A[x] = d;
    for(int i=0; i<G[x].size(); i++)
        dfs(G[x][i], d);
}

int main() {
    int u, v;
    scanf("%d%d", &N, &M);
    for(int i=1; i<=M; i++) {
        scanf("%d%d", &u, &v);
        G[v].push_back(u); //反向建边 
    }
    for(int i=N; i; i--) dfs(i, i); 
    for(int i=1; i<=N; i++) printf("%d ", A[i]);
    printf("\n");
    return 0;
}

你可能感兴趣的:(图论,DFS)