拓撲排序//SDNUOJ1089

第一行——咕咕咕。

果然是一個咕起來就停不下來的博主。

 

拓撲排序:

1.適用於有向無環圖。即不存在後面出現的節點指向前面的節點。

2.本質上是對圖中的節點進行排序。按入度爲零排序。不存在入度爲零的點則有環,不存在拓撲排序。

3.意義:其實我也不知道有啥用。存在先後順序,所以可以用來排序(???)

4.啊!我想起來了,數據結構上用來解決排課問題了!就是類似大一上學了c語言大一下才可以學數據結構這種,因爲c是數據結構的先導課。

5.示例代碼複雜度高,可以用鄰接表存圖,時間複雜度要低一些。

6.也可以用隊列進行優化。(畢竟這O(n^2)基本上1e^3以上就不行了

7.考慮到有些題目需要進行排序(例如按字典序輸出,可以在6的基礎上使用優先隊列。

 

本代碼以SDNU1089爲例——是一份很好理解但時間複雜度高的代碼O(n^2)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define ll long long

using namespace std;

int a[1001][1001] = {0};

int main()
{
    int n,m;
    int b[1001] = {0};
    int v[1001];
    bool vis[1001] = {0};
    int tot = 0;
    int f = 0;
    scanf("%d%d",&n,&m);
    for(int i = 0; i < m; ++i)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        a[x][y] = 1;//從x->y有邊
        b[y]++;//y的入度++
    }
    for(int i = 1; i <= n; ++i)
    {
        int flag = 0;
        for(int j = 1; j <= n; ++j)
        {
            if(b[j] == 0&&!vis[j])
            {
                flag = 1;
                v[tot++] = j;
                vis[j] = 1;
                break;
            }
        }
        for(int j = 1; j <= n; ++j)
        {
            if(a[v[tot-1]][j] == 1)
            {
                b[j]--;
                a[v[tot-1]][j] = 0;
            }
        }
        if(flag == 0)
        {
            printf("IMPOSABLE\n");
            f = 1;
            break;
        }
    }
    if(!f)
        for(int i = 0; i < tot; ++i)
        {
            if(i == 0)
                printf("%d",v[i]);
            else
                printf(" %d",v[i]);
        }
    return 0;
}

 

補充練習:

其他拓撲排序練習題

這是偶然發現的練習題列表!雖然裏面的題我就做過一個!後續會補的!

OpenJ_Bailian-4084

HDU1285

與上面示例代碼不同的是,這兩個題要考慮重邊問題。(我已經被坑了很多次了,我愉快的決定以後啥都考慮重邊

SDNUOJ1031

這個需要每次都排序,我wa了好幾次,附的是題解博客,裏面有題目鏈接。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章