題意:
給一張有向無環圖,可以刪掉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時間複雜度...