學術篇 2 28測試T2 線段 拓撲排序

2022-07-22 05:33:10 字數 1833 閱讀 3076

題目:

思路:看到這種找前後的題目... 第一反應就是拓撲排序_(:з」∠)_

每條線段都有左右兩個端點咯, 然後就亂搞吧..

我們用\(i\)和\(i'\)分別表示第\(i\)條線段的左右端點..

然後如果\(x\)在\(y\)的左邊, 那麼\(x'\)一定小於\(y\), 我們就建一條\(x'->y\)的邊

如果\(x\)與\(y\)相交, 那麼一定\(x且\(y(顯然), 我們就分別建\(x->y'\)和\(y->x'\)兩條邊.

然後對於每個點\(x\), \(x, 那麼再建\(x->x'\)的邊...

然後為了字典序, 把編號扔進乙個小根堆裡維護一下, 按照堆的順序跑一邊拓撲排序大約就可以了吧..

wrong的情況也很好特判, 只要判斷進隊的點的個數不到\(2n\)就好了...

輕鬆加愉快地過了樣例. 於是這樣就做完了?

然後非常無恥地找了一下資料一測, 發現得到了10pts... 就是輸出wrong的10分...

然後發現順序全錯了...這就很尷尬...

那就開啟組資料看一下嘛, 反正\(n\leq10\)的資料很適合手玩..

然後第二組資料(\(n\)最小的一組)是這樣的:

7 4

2 1 7

2 2 7

1 7 5

2 4 2

我們來畫一下:

就可以看出問題了. 如果我們這麼做,在\(x\)進堆之前, 若\(\exists\)邊\(y->x\)且\(\exists u滿足x, 則拓撲序列將變為\(u y x\)而不是\(y x u\), 字典序就不優了..(看清楚題目的字典序指的是什麼..)

那怎麼辦啊? 為了解決這個問題, 我們考慮把邊都反向, 堆變成乙個大根堆, 然後順序從後向前做(就是最後把拓撲序列倒過來), 就可以了..

因為我們發現, 這麼一搞, 存在依賴的編號較小的點將會比較靠後的彈出, 倒過來就變成優先了, 也就滿足了字典序的要求..

然後想到這一點就沒什麼難度了...

std好像用了手寫堆, 但是我人懶就直接上priority_queue咯, 不過跑的還是飛快, 最大的點也用不到0.3s..

**:

#include #include #include using namespace std;

const int n=202020;

priority_queueq;

inline int gn(int a=0,char c=0)

struct edgee[n];

int v[n],du[n],ans[n],tot,cnt,n,m;

inline void buildedge(int x,int y)

int main()n<<=1;

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

if(!du[i]) q.push(i); cnt=n;

while(!q.empty())

ans[x]=cnt--;

} if(cnt) puts("wrong");

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

printf("%d %d\n",ans[i],ans[i+1]);

}

5 11返校測試T2

有k k第一行乙個整數n。第二行有n個正整數,每個數字代表一張選票所選的人的編號。每行乙個正整數,為優勝者的編號,由小到大。如果沒人獲勝,則輸出 no such person.8 5 2 3 6 2 5 2 72優勝者為2號。下面是這個題的思路qwq 將所有的選票進行從小到大排序 快排解決 然後將陣...

2018 10 27測試T2 洗衣服

傳送門 一道貪心題,但考場上沒貪出來 維護兩個堆,分別存洗衣服和烘乾衣服的時間 每次加進來一件衣服,就在之前最早結束的那一台機器裡操作,這樣會是最優的 洗衣服和烘乾衣服都這樣搞,最後再用最大配最小的原則求最大值就行了 include include include include define n ...

2018 11 02測試T2 飛越行星帶

傳送門 這道題比較妙啊 把每個行星看成乙個點 把 x xx 軸和 y l y ly l 看成兩個特殊的點 把行星之間的距離看做邊 每個點與 x xx 軸的邊為 y iy i yi 與 y l y ly l 的邊為 l y il y i l yi 從小到達加邊,如果發現 x xx 軸和 y l y l...