洛谷P3961 圖的遍歷

題目來源ios

 

作這道題的方法很多。ui

在這裏我只提一種spa

就是大法師。code

能夠採用反向建邊,從最大的點開始dfsblog

咱們考慮每次從所剩點中最大的一個點出發,咱們暫且稱它爲i,而凡是i這個點所能到達的點,能夠到達的點最大都是i。遞歸

在遍歷的時候按n——>1的順序ci

由於是從大到小遍歷,故每一個點第一次被碰到的i必定是這個點最大可到達的點get

代碼以下it

#include<iostream>
#define maxx 500010
using namespace std;
int n,m;

struct pp {
    int next,to;
} edge[maxx];
int cnt;
int head[maxx];

int a[maxx];//存儲答案
void add(int u,int v) {        //鄰接表
    edge[++cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt;
}
void dfs(int x,int k) {
    if(a[x]) return ;    //處理環,同時保存最優解
    a[x]=k;
    for(int i=head[x]; i; i=edge[i].next)//遍歷能夠到達的點
        dfs(edge[i].to,k);
}
inline void init() {        
    for(int i=1; i<=n; i++)
        head[i]=-1;
}
int main() {
    cin>>n>>m;
    init();        //初始化
    for(int i=1; i<=m; i++) {
        int u,v;
        cin>>u>>v;
        add(v,u);    //反向建邊
    }
    for(int i=n; i>=1; i--) dfs(i,i);    遞歸搜索
    for(int i=1; i<=n; i++) cout<<a[i]<<' ';
}

同時能夠使用vector,代碼更爲易讀,變量同上io

#include<iostream>
#include<vector>
#define maxx 500100
using namespace std;
int n,m;
vector<int > edge[maxx];
int a[maxx];
void dfs(int x,int k) {
    if(a[x]) return ;
    a[x]=k;
    for(int i=0; i<edge[x].size(); i++)
        dfs(edge[x][i],k);
}
int main() {
    cin>>n>>m;
    for(int i=1; i<=m; i++) {
        int u,v;
        cin>>u>>v;
        edge[v].push_back(u);
    }
    for(int i=n; i>=1; i--) dfs(i,i);
    for(int i=1; i<=n; i++) cout<<a[i]<<' ';
}
相關文章
相關標籤/搜索