たのしい工学

プログラミングを学んで、モノをつくりたいひと、効率的に仕事をしたい人のための硬派なブログになりました

[ALDS_1_11_D] 深さ優先探索アルゴリズムの隣接リストパターンはスタックで

   

AOJのALDS1_11_D: Connected Componentsの問題を解いてみました。こちらのプログラムはSNSなどで相互フォロー関係をたどり、任意の相手にたどりつくことができるかを判定するものです。とりあえずプログラムはこちら。

#include <iostream>
#include <vector>
#include <stack>
#define MAX 100000
#define NIL -1

using namespace std;

int n, m, s, t, q;
vector<int> G[MAX];
int group[MAX];

//深さ優先探索で頂点間の関係性を決定します。
void dfs(int r, int c){
    stack<int> S;// stackでバッファリング
    S.push(r);
    group[r] = c;// その頂点rをgroupに分類
    while(!S.empty()){
        int u = S.top(); S.pop(); // stackから頂点を取り出す
        for(int i=0; i<G[u].size(); i++){ //隣接リストで頂点uに隣接する頂点を探す
            int v = G[u][i] //隣接する頂点vを取り出す
            if(group[v]==NIL){ // 隣接する頂点vがどこかの隣接する頂点グループに属するかを判定
                group[v]=c;// どこの頂点の隣接でもなければ、頂点vをcグループとして分類
                S.push(v);//このまま頂点vの隣接頂点の状態を探索するために頂点vをstack
            }
        }
    }
}

void makeGroup(){
    int id =1;
    for(int i=0; i<n;i++){//グループの初期化
        group[i]=NIL;
    }
    for(int u=0; u<n; u++){
        if(group[u]==NIL){//グループに所属していない頂点について深さ優先探索していく
            dfs(u,id++);
        }
    }
}

int main(){

    cin >> n >> m;

    for(int i=0; i < m; i++){
            cin >> s >> t;
            G[s].push_back(t);// 頂点sと頂点tは友人関係、つまり無向グラフとして表現される
            G[t].push_back(s);// 頂点sと頂点tは友人関係、つまり無向グラフとして表現される
    }

    makeGroup();

    cin >> q;

    for(int i=0; i < q; i++){
        cin >> s >> t;
        if(group[s]==group[t]){//頂点sと頂点tが同一グループに所属するかを判定。同一グループであるなら、友人を経由してsとtはつながることが可能
            cout << "yes" << endl;
        }else{
            cout << "no" << endl;
        }
    }

    return 0;

}

stackでデータを保持するのがポイントです。グループ未所属で、現在の頂点に隣接する頂点を深さ優先探索によって探索し、グループの状況を判定し、グループわけを実行していきます。

 - コンピュータサイエンス, アルゴリズム