hdu 5195 拓撲排序 貪心

2021-06-29 10:39:58 字數 1672 閱讀 6115

題意:

給一張有向無環圖,可以刪掉k條邊,要求刪掉k條邊以後的無環圖拓撲排序後字典序最大。

解析:第一次a出bc的第二題,可惜第一題不能化簡(1/1 ->> 1),還是掉分了,發個部落格紀念一下。

首先是有向無環圖(dag)的拓撲排序。

拓撲排序意思是先找每個入度為零的點,排在最先,然後將這個點有關邊全部刪除,更新其他點的入度;

重複上句話,直至圖已空,為了保證排序後下標字典序最大,使用優先佇列來維護。

然後本題巧在貪心,為了達到字典序最大,刪除邊的時候,我最先刪除的是下標最大的點的入度,然後依次,(若不能刪則跳過)。

開始wa的原因是沒有考慮到一種情況,就是

5 5 2

1 55 2

2 44 3

5 4這樣一組資料。

如圖:

若按照我的貪心方法,我將刪掉邊(1->5),(4 -> 3),此時拓撲排序的輸出將會是5, 3, 2, 1, 4。

實際上,我們注意到,當5這個點被刪掉的時候,它指向4的那條邊也被刪掉了,所以如果我提前刪掉邊(2 -> 4),可以達到更好的效果。

所以我提前定義了乙個tdu 來代表當前du,刪擁有tdu的點就行了。

詳見**。

ps.題解裡面用的是線段樹維護什麼的,不知道是最後減了大資料沒超時還是怎麼的讓我過了,這個演算法的時間複雜度是o(nm),主要耗時在度的計算上。

**:

#include #include #include #include #include #include #include #include #include #include #include #include #define ll long long

using namespace std;

const int maxn = 1e5 + 10;

const int inf = 0x3f3f3f3f;

const double eps = 1e-8;

const double pi = acos(-1.0);

const double ee = exp(1.0);

vector g[maxn];

int du[maxn];

int tdu[maxn];

int n, m, k;

int l[maxn];

void toposort()

for (int i = 1; i <= n; ++i)

for (int i = n; i >= 1; --i)

if (tdu[i] <= k)

}int tot = 0;

priority_queue q;

for(int i = 1 ; i <= n ; ++i)

if(!du[i])

q.push(i);

while(!q.empty())}}

for (int i = 0; i < tot - 1; i++)

printf("%d\n", l[tot - 1]);

return;

}int main()

for (int i = 1; i <= m; i++)

toposort();

}return 0;

}

hdu 拓撲排序歸納

拓撲排序,其本質是輸出乙個全序關係,對於按要求輸出給定關係的題目,一般就是按照題目要求實現這個全序關係,這種題時常會先給乙個偏序關係,然後給出剩下的元素如何建立關係 字典序之類的 如果忘了那幾個詞是啥意思.偏序關係 滿足自反,反對稱,傳遞性的關係 全序關係 乙個偏序關係r,且對任意x,y有xry或y...

貪心演算法 拓撲排序

關於貪心演算法介紹 乙個複雜的工程,經常可以分解成一組簡單一些的任務,這些任務完成了,整個工程就完成了。例如汽車組裝問題可以分解成 底盤安裝 車軸安裝 車輪安裝 座位安裝 噴漆 剎車安裝 車門安裝等。但是這些任務之間有個先後順序,例如車軸安裝之前先要進行底盤安裝。類似的問題,可以將任務和人物的先後順...

hdu1285(拓撲排序)

拓撲排序簡單來說就是把乙個圖的所有節點排序,使得每一條有向邊 u,v 對應的u都排在v的前面。拓撲排序最大的用途就是判斷乙個有向圖是否有環,當然判斷還有一種方法就是floyd演算法。如果用鄰接表的話拓撲排序的時間複雜度是o n e 鄰接矩陣是o n 2 n表示頂點數,e表示邊數,floyd時間複雜度...