在某些演算法中,尤其是樹、圖、資料結構相關的演算法,會牽扯到大量的遞迴。在絕大部分的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...