グラフのトポロジカルソート -- カーンのアルゴリズム

学生時代に誰もがそんな状況に遭遇したことがあると思いますが、上級コースでは基礎コースを修了しないと勉強できないものもあります。「図 11. コース関係図」では、コース C を選択する場合は最初にコース B を完了する必要があり、コース B を選択する場合は最初にコース A を完了する必要があります。

この時点で、「トポロジカルソート」の助けが必要になります。「トポロジカルソート」は、有向非巡回グラフ用のアルゴリズムです。これは、「グラフ」内のすべての頂点を順番に線形に並べ替えることです。つまり、頂点 u と頂点 v がある場合、頂点 v に到達したい場合は、頂点 u に到達する必要があります。次に、「トポロジカルソート」では、頂点 u が頂点 v の前になければなりません。

カーンアルゴリズムの手順は次のとおりです。

  1. 各ポイントの現在の入次数を記録する度数配列を作成し、すべての値を 0 に初期化します。
  2. すべてのエッジを走査し、次数配列を更新します
  3. キューを作成する
  4. キューが空でない場合、ポイントがキューから取り出され、ソートされた配列に記録され、次数の対応する位置が -1 に設定され、そこから直接到達できるすべてのポイントが検索され、これらのポイントの次数が計算されます。全て1ずつ減ります。
  5. 度数配列を走査し、最初に見つかった点を値 0 でキューに入れます。
  6. キューが空でない場合は、2 つのステップでループ 45 を実行します。

スケジュールⅡ

これで、受講するコースの合計が numCourses になり、0 ~ numCourses - 1 で示されます。prerequisites[i] = [ai, bi] という配列の前提条件が与えられます。これは、ai コースを受講する前に bi を受講する必要があることを意味します。

たとえば、コース 0 を学習するには、まずコース 1 を完了する必要があります。これは、一致 [0,1] で示されます。
すべてのコースを完了するために設定した学習の順序を返します。正しい注文が複数ある場合がありますが、どれか 1 つを返品するだけで済みます。すべてのコースを完了できない場合は、空の配列を返します。

 効率を向上させるために、エッジを隣接行列に変換して保存します。

public class Solution {
    public int[] FindOrder(int numCourses, int[][] prerequisites) {
        int[] res=new int[numCourses];
        if(numCourses==1)
        {
            res[0]=0;
            return res;
        }
        int[] degree=new int[numCourses];
        bool[,] matrix=new bool[numCourses,numCourses];
        for(int i=0;i<numCourses;i++)
        {
            degree[i]=0;
            for(int j=0;j<numCourses;j++)
                matrix[i,j]=false;
        }
        for(int i=0;i<prerequisites.Length;i++)
        {
            degree[prerequisites[i][0]]++;
            matrix[prerequisites[i][1],prerequisites[i][0]]=true;
        }
        Queue<int> q=new Queue<int>();
        int a=0;
        do
        {
            if(q.Count!=0)
            {
                int degree0=q.Dequeue();
                res[a++]=degree0;
                degree[degree0]=-1;
                for(int i=0;i<numCourses;i++)
                if(matrix[degree0,i])
                degree[i]--;
            }
            for(int i=0;i<numCourses;i++)
            if(degree[i]==0)
            {
                q.Enqueue(i);
                break;
            }
        }while(q.Count!=0);
        if(a==numCourses)
        return res;
        else
        {
            int[] empty=new int[0];
            return empty;
        }
    }
}

おすすめ

転載: blog.csdn.net/qq_43533956/article/details/124180422