BZOJ2125 最短路 仙人掌最短路

2021-08-14 12:16:32 字數 2010 閱讀 7088

給乙個n個點m條邊的連通無向圖,滿足每條邊最多屬於乙個環,有q組詢問,每次詢問兩點之間的最短路徑。

輸入的第一行包含三個整數,分別表示n和m和q 下接m行,每行三個整數v,u,w表示一條無向邊v-u,長度為w 最後q行,每行兩個整數v,u表示一組詢問

輸出q行,每行乙個整數表示詢問的答案

9 10 2

1 2 1

1 4 1

3 4 1

2 3 1

3 7 1

7 8 2

7 9 2

1 5 3

1 6 4

5 6 1

1 95 7

對於100%的資料,n<=10000,q<=10000

仙人掌的題目,都與樹上的方法相聯絡,再考慮環的影響

首先如果在樹上,我們設d[u]表示u到根的距離,兩點u,v的距離di

s=d[

u]+d

[v]−

2∗d[

lca]

現在加上幾個環,我們先跑一遍dfs找出所有的環以及算出d,然後重構樹,將環上的點全部連到該環最高點上,距離為環上到最高點的最短路

這樣子構建出來的樹,我們可以用倍增套用樹的方法求解

如果求解時兩點倍增時算得的最後祖先屬於同乙個環,那麼就考慮環的貢獻

#include

#include

#include

#include

#include

#define ll long long int

#define rep(i,n) for (int i = 1; i <= (n); i++)

#define redge(u) for (int k = h[u]; k; k = ed[k].nxt)

using namespace std;

const int maxn = 10005,maxm = 100005,inf = 1000000000;

inline int rd()

while (c >= 48 && c <= 57)

return out * flag;

}int n,m,q,h[maxn],ne = 2;

struct edgeed[maxm];

inline void build(int u,int v,int w); h[u] = ne++;

ed[ne] = (edge); h[v] = ne++;

}int h2[maxn];

struct ee[2 * maxn];

inline void add(int u,int v); h2[u] = ne++;}

int dfn[maxn],low[maxn],d[maxn],dep[maxn],cnt = 0;

int fa[maxn][20],dis[maxn][20];

int cir[maxn],siz[maxn];

void getcir(int rt,int k)

}void dfs(int u)else low[u] = min(low[u],dfn[to]);

if (dfn[u] < low[to]) add(u,to),dis[to][0] = ed[k].w;

}redge(u) if (fa[to = ed[k].to][0] != u && dfn[u] < dfn[to])

getcir(u,k);

}void dfs2(int u)

for (int k = h2[u],to; k; k = e[k].nxt)

}int solve(int u,int v)

if (cir[u] && cir[u] == cir[v])

ans += min(abs(d[u] - d[v]),siz[cir[u]] - abs(d[u] - d[v]));

else ans += dis[u][0] + dis[v][0];

return ans;

}int main()

return 0;

}

BZOJ2125 仙人掌 最短路

題意 求仙人掌上的多元最短路 考慮如果在樹上,u,v兩點之間的最短路為dis u dis v 2 dis lca 因為仙人掌每個點只屬於乙個簡單環,先dfs弄清仙人掌的結構,對於環把環中離根節點最近的點作為父親,環中其他點向這個點連邊,這樣就建出一棵新的樹,如果u,v的lca不在環上,就按照樹的做法...

BZOJ2125 仙人掌 最短路

bzoj2125 建出圓方樹,圓方邊的權值為圓點到環上最高點在dfs樹上的點的距離,這樣就可以記錄下環上兩個點的距離 並在方點處記錄一下環的總長,因為環上兩點間有兩條路徑可走,要分類討論 然後就是樹上求dis的問題,先求lca 然後lca如果是圓點就直接求距離 如果是方點就分類討論一下就好了 cod...

仙人掌最短路 BZOJ 2125 最短路

題解 首先如果這是一棵樹的話,那麼我們只需要選定乙個根,之後掃一遍這棵樹,詢問的話即是兩點到根節點的距離之和減去二倍的兩點lca到根節點距離。那麼如果是一棵仙人掌的話,我們強行套用這個辦法,重新構造一棵樹。對於仙人掌中的乙個環來說,我們把該環中深度最小的點當做這個環的根,然後環上其他點連向該環,非環...