農夫約翰有n(2<=n<=40000)個農場,標號1到n。m(2<=m<=40000)條的不同的垂直或水平的道路鏈結著農場,道路的長度不超過1000.這些農場的分布就像下面的地圖一樣,圖中農場用f1..f7表示:
每個農場最多能在東西南北四個方向鏈結4個不同的農場。此外,農場只處在道路的兩端。道路不會交叉而且每對農場間有且僅有一條路徑。鄰居鮑伯要約翰來導航,但約翰丟了農場的地圖,他只得從電腦的備份中修復率。每一條道路的資訊如下:
從農場23往南經距離10到達農場17
從農場1往東經距離7到達農場17
. . .
最近美國過度肥胖非常普遍。農夫約翰為了讓他的奶牛多做運動,舉辦了奶牛馬拉松。馬拉松路線要盡量長。
奶牛們拒絕跑馬拉松,因為她們悠閒的生活無法承受約翰選擇的如此長的賽道。因此約翰決心找一條更合理的賽道。他打算諮詢你。讀入地圖之後會有k個問題,每個問題包括2個整數,就是約翰感興趣的2個農場的編號,請盡快算出這2個農場間的距離。
輸入格式
第1行:兩個分開的整數n和m。
第2到m+1行:每行包括4個分開的內容,f1,f2,l,d分別描述兩個農場的編號,道路的長度,f1到f2的方向n,e,s,w。
第2+m行:乙個整數k(1<=k<=10000).
第3+m到2+m+k行:每行輸入2個整數,代表2個農場。
輸出格式
對每個問題,輸出單獨的乙個整數,給出正確的距離。
樣例樣例輸入
7 6
1 6 13 e
6 3 9 e
3 5 7 s
4 1 3 n
2 4 20 w
4 7 2 s
31 6
1 42 6
樣例輸出13
336
注意到每兩個農場間只有一條路相連. 那就是一棵樹, 至於方向, 完全沒有意義,在讀入時直接忽略即可
兩個節點間的最短路, 就可以用lca求, 這裡我們用tarjan求lca:
我們需要兩個邊表, 乙個儲存原圖, 乙個儲存詢問.
看注釋吧
#include#include#includeusing namespace std;
const int maxn = 80005;
int n, m, head[maxn], len=-1, dfn[maxn], tot=-1, headq[maxn], vis[maxn], dis[maxn], f[maxn];
struct edgee[maxn], q[maxn];
void add(int x, int y, int w)
void add_que(int u, int v)
void init(int n)
int find(int x)
void tarjan(int root)
} for(int i=headq[root]; ~i; i=q[i].nx) }}
int main()
int k; scanf("%d", &k);
for(int i=1; i<=k; i++)
tarjan(1);
for(int i=0; i在這裡我解釋一下為什麼find(v)就可以求出lca
看這個圖.
假如我們求4 , 7 間的最短路.
在我們tarjan的時候, 只有根節點的子樹都tarjan完時,才會更新他並查集父節點.當我們tarjan(7)時,發現有和7有關的詢問,並且4已經訪問過, 這時f[3]仍為3, find(3) 就是3, 即lca, 假如4還有子樹的話, tarjan(7)時4這邊的子樹已經訪問完, fa[3]已經更新, 所以, 我們可以這樣求出lca
Tarjan演算法求LCA
題源 這個題還是debug了好久。1.呼叫函式中如果要更改外部資料需要傳遞引用,其實傳遞引用往往效率更高,以後要多加注意這一點。2.忘寫並查集了 捂臉逃 3.題目要求的是距離而不是lca,認真審題。貼 include include include define maxn 100005 define...
Tarjan演算法求LCA(最近公共祖先)
lca的離線演算法。複雜度為o n q 這個演算法充分利用了dfs樹的結構。對於每個節點u,關於它的詢問 u,v 只有兩種。假設先dfs u 後dfs v 1 v在u的子樹內。此時lca u,v u.2 v不在u的子樹內。假設v在u的父親的另一棵子樹內。此時lca u,v father u 如果不滿...
Tarjan離線演算法求最近公共祖先(LCA)
arjan離線演算法求lca介紹 前言 首先,本人搞懂tarjan求最近公共祖先 lca 也是瀏覽了大量其他大牛的文章,若是看了本文仍未弄懂的,可以嘗試自己做一下模板題 裸題 hdu2586,自己用資料去感受一下,或者可以換篇文章再看,或許他的文章更對你的 胃口 一 概念介紹 1 最近公共祖先 對於...