OI競賽中手工棧的書寫

2021-07-28 05:47:55 字數 2360 閱讀 4566

在某些演算法中,尤其是樹、圖、資料結構相關的演算法,會牽扯到大量的遞迴。在絕大部分的oi競賽中(noip、noi等),遞迴所占用的棧空間限制為記憶體限制,換句話說,就是一般只要你不mle就不會爆棧。

但是sdoi歷年使用windows+cena評測,這個古老的評測系統遞迴的棧空間有限,經常遞迴到3w+就會爆棧,也就是說,如果你想遍歷一條10w級別的樹鏈是不可能的。

所以sdoi的選手們就開始寫手工棧這個東西。。什麼是手工棧呢?其實就是根據遞迴的原理用乙個棧代替遞迴的棧空間,然後進行的操作什麼的是不變的。本文將給出一些常用演算法手工棧的書寫。

手工棧的主要部分和大體寫法如下:

1、stack:手工棧。「手工棧」實際上就是這個陣列,作為乙個棧儲存的是當前遍歷到的所有點,模擬遞迴的過程。某乙個點在棧內說明它並沒有利用完成,某乙個點已經出棧說明其所有的資訊都已經利用過了。

2、cur:當前弧。資料結構中儲存邊的最常用方法是nxt陣列(鍊錶),而cur表示的就是這個點當前已經遍歷到了它的哪一條邊。會isap的同學可以發現這個和isap的當前弧是差不多的。

3、use:標記陣列。有時需要用有時不需要用。有的遞迴過程在某乙個點第一次遍歷到的時候需要記錄一些資訊(比如dfs序等),這個時候就需要用到標記陣列判斷當前點是否是第一次遍歷到。

演算法流程:

1、將第乙個點入棧

2、只要棧非空就一直訪問棧頂

3、當棧頂的點所有資訊都已經被利用就彈棧

注意:需要統計資訊的時刻無非:某個點入棧、某個點第一次被訪問、某個點出棧,在相對應的時刻統計資訊就行了。

**可以參考下文

例題:bzoj4034

就是一道鏈剖+dfs序裸題

void dfs_1(int x,int fa)

}void dfs_2(int x,int fa)

void dfs_1()

continue;

}int vt=v[cur[x]];stack[++tmp]=vt;

father[vt]=x;size[vt]=1;h[vt]=h[x]+1;

cur[x]=nxt[cur[x]];

}}void dfs_2()

continue;

}while (cur[x]&&(v[cur[x]]==father[x]||v[cur[x]]==son[x])) cur[x]=nxt[cur[x]];

if (!cur[x])

int vt=v[cur[x]];stack[++tmp]=vt;

top[vt]=vt;in[vt]=++dfs_clock;num[dfs_clock]=a[vt];

cur[x]=nxt[cur[x]];

}}

完整** 戳這裡

例題 bzoj1051

如果要是出題人出一條鏈來卡你的話也是會爆棧的。。

主要是tarjan本來就需要用棧好煩啊

void tarjan(int x)

else

if (vis[v[i]])

low[x]=min(low[x],dfn[v[i]]);

if (dfn[x]==low[x])

}}

void tarjan(int x)

}if (father[x]) low[father[x]]=min(low[father[x]],low[x]);

continue;

}int vt=v[cur[x]];

if (!dfn[vt])

else

if (vis[vt]) low[x]=min(low[x],dfn[vt]);

cur[x]=nxt[cur[x]];

}}

完整** 戳這裡

例題 bzoj1854

這種需要返回引數的東西有點gg,自己yy了乙個有點麻煩的寫法。。。

bool find(int x,int k)

}return

false;

}

void find(int x,int k)

while (cur[x]&&vis[v[cur[x]]]==k) cur[x]=nxt[cur[x]];

if (!cur[x])

int vt=v[cur[x]];

vis[vt]=k;

if (!belong[vt])

cur[belong[vt]]=point[belong[vt]];

stack[++top]=belong[vt];

}}

完整** 戳這裡

感覺點分寫手工棧最蛋疼啊。。遞迴的次數太多要寫3次。。

OI中的小智慧型

反正不會咕咕的。sort之類沒 1的問題不說 雙向邊n 2的問題不說 變數n 5的問題不說 1.先生成後判斷 見noip 2016 pj t2回文日期 這個思想在這道題體現的不明顯,記得洛谷上面有個回文素數的題,如果暴力列舉每個數直接tle,但是先生成前一b,然後得到該段回文d,可以得到bd 如果這...

A 演算法在OI中的應用

1.a 演算法 我們普通的搜尋演算法往往複雜度都是指數級,oi中這樣的複雜度無法滿足我們的要求。這時我們一般都會進行一些剪枝優化,但在有些題目中卻可以有更加巧妙的方法 a 演算法。a 演算法作為一種基礎的啟發式搜尋,它不同於dfs和bfs將所有情況進行遍歷,它能從所有情況中選出較優的再進行遍歷。因此...

EF 中事務的書寫

在ef 中怎麼使用事務?這個問題糾結了我好久,直到有人跟我一起討論,我和同事一起討論查資料。查的好多資料都是使用 using transactionscopescope newtransactionscope 這種方式。而我在實際使用中是沒法使用的。所以我就一直找其他的方式,無意中看到某個 的的da...