拓撲排序,其本質是輸出乙個全序關係,對於按要求輸出給定關係的題目,一般就是按照題目要求實現這個全序關係,這種題時常會先給乙個偏序關係,然後給出剩下的元素如何建立關係(字典序之類的)。
如果忘了那幾個詞是啥意思...
偏序關係:滿足自反,反對稱,傳遞性的關係
全序關係:乙個偏序關係r,且對任意x,y有xry或yrx
哈斯圖:對乙個偏序關係畫的圖,每個點為關係中的元素,其中,對兩點x,y,若有xry則y畫在x上方,若有xry且不存在s滿足xrs,sry則在x,y中連線。一般情況下把題目裡面給的關係直接畫出來再分下層就是哈斯圖了。和正常的哈斯圖不同,為了方便看我們一般會在上面標上箭頭。
拿下面這個圖說事,按之前的說法,6-2和6-1都在這個偏序關係裡面(傳遞性)但是因為6和1裡面連著2就不在他倆連線了,同樣對於拓撲排序的題,題目裡面說了6-2和2-1以後由傳遞性就有6-1了,不要拘泥於概念
畫上箭頭。拓撲排序的效果在於把偏序關係線性輸出,在這個裡面5,6,7之間沒有確定的順序,還有就是可以按照8-5-6-2這樣的順序,在7之前輸出2,沒有說同層的必須連著輸出。對於這種狀況按什麼順序輸出是乙個考點,經常會把這個順序根點的標號扯上關係,加上拓撲排序裡面用到乙個佇列,所以時常會在此處把佇列操作成優先佇列
然後就是拓撲排序可以用於判斷有向環,如果在排序中排出來的點比圖上的總點數少就說明有有向環。如果乙個關係裡面出現了環,自然就不滿足反對稱性了(ex:xry,yrz,zrx則由傳遞性有xrz與zrx一起不滿足反對稱性),然後它就不是乙個偏序關係了,所以如果判出來了環的情況論上就不會有下一步操作了。無向環用並查集判斷
另外還有的題就是要你確定乙個偏序關係,比如統計同樣的偏序(可以理解為哈斯圖上面同一層的元素)每個有多少
因為拓撲排序這個東西本身比較直觀符合大眾認知,直接給個裸的拓撲排序顯得太親民,所以如果看見他出現,一般都會是繞了幾個彎,變成一道智商題,想直接寫乙個拓撲排序然後就過了不大現實,搞清楚拓撲排序的思想比較重要,方便在關鍵時刻能夠胡搞的出來。
常用操作:
反向建圖:有時會出現=需要把題目所給的偏序反過來的情況,比如下面的2647
把佇列換成優先佇列
hdu1285
比較純的拓撲排序,因為要按照字典序輸出拓撲序相同的元素,以及時間多,所以可以不使用佇列而是暴力遍歷
#include using namespace std;
const int maxn=500;
int main()
for(int i=1;i<=v;i++)
int coun=v;
queueq;
for(int i=0;ihdu2647
使用拓撲排序判環並且判斷點在拓撲序上的層次,我的思路是維護兩個值,乙個值記錄現在的層次,另乙個值維護當前層次下,佇列中還有多少個元素。另外還要反向建圖
#include using namespace std;
int main()
int coun=v;
queueq;
int levl=0,cur=0,tot=0;
for(int i=1;i<=v;i++)
}// for(int i=0;ihdu1811
這個題是拓撲排序和並查集的結合,需要拿並查集預處理後拿拓撲排序判斷是否有唯一拓撲序和是否有拓撲序
#include using namespace std;
const int maxn=10005;
int fa[maxn];
int findfa(int vt)
struct edge
ed[maxn*2];
int main()
else
}queueq;
for(int i=0;i1)flag=true;
int vt=q.front();
q.pop();
sum--;//cout<
這個題把拓撲排序用的佇列換成優先佇列以後再處理一下就行了
#include using namespace std;
vectoradjl[100010];
long long c,su;
int v,e,s,t,in[100010];int ans[100010],countt;
void top_sort()
printf("%i64d\n",su);
//for(int i=0;ihdu4857
反向建圖,大根堆做佇列,反向輸出
#include using namespace std;
const int maxn=30005;
int main()
int fr,to;
for(int i=1;i<=e;i++)
int coun=1;
//top_sort;
priority_queueq;
vectorvec;
for(int i=1;i<=v;i++)if(in[i]==0)
while(!q.empty())
return 0;
}
hdu1285(拓撲排序)
拓撲排序簡單來說就是把乙個圖的所有節點排序,使得每一條有向邊 u,v 對應的u都排在v的前面。拓撲排序最大的用途就是判斷乙個有向圖是否有環,當然判斷還有一種方法就是floyd演算法。如果用鄰接表的話拓撲排序的時間複雜度是o n e 鄰接矩陣是o n 2 n表示頂點數,e表示邊數,floyd時間複雜度...
HDU 2647拓撲排序
還有乙個地方需要注意 判斷輸出 1的情況不能只判斷沒有乙個入度為0的點,因為有可能在中間就出現矛盾了,如 a b c d c 有入度為0的點,但卻要輸出 1 include include include includeusing namespace std define max 10005 int...
hdu 1285(拓撲排序)
題意 給各個隊間的勝負關係,讓排名次,名詞相同按從小到大排。解析 拓撲排序是應用於有向無迴路圖 direct acyclic graph,簡稱dag 上的一種排序方式,對乙個有向無迴路圖進行拓撲排序後,所有的頂點形成乙個序列,對所有邊 u,v 滿足u 在v 的前面。該序列說明了頂點表示的事件或狀態發...