第一行——咕咕咕。
果然是一個咕起來就停不下來的博主。
拓撲排序:
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;
}
補充練習:
這是偶然發現的練習題列表!雖然裏面的題我就做過一個!後續會補的!
與上面示例代碼不同的是,這兩個題要考慮重邊問題。(我已經被坑了很多次了,我愉快的決定以後啥都考慮重邊
這個需要每次都排序,我wa了好幾次,附的是題解博客,裏面有題目鏈接。