洛谷P4949 最短距離

2021-10-01 05:51:37 字數 2410 閱讀 8532

給出乙個 n 個點 n 條邊的無向連通圖。

你需要支援兩種操作:

修改 第 x 條邊的長度為 y ;

查詢 點 x 到點 y 的最短距離。

共有 m 次操作。

思路

n個點n條邊的無向連通圖(簡單圖),如果少一條邊就是形成一棵樹,就是一道lca題,這題多了一條邊,就要用相應的方法處理這條邊。

考慮剔除的邊是(uu,vv),權值為w,那麼 (u,v) 的最短距離就是 min(dis(u,v),dis(u,uu)+dis(v,vv)+w,dis(u,vv)+dis(v,uu)+w)。

dis(u, v)=dis(root, u) + dis(root, v) - 2 * dis(root, lca(u, v))。

所以就是維護乙個dis值。

考慮到對一條邊修改,就會修改這條邊下方所有的dis的權值,所以是區間更新;查詢是單點查詢。所以用樹狀陣列維護。

又因為是樹形結構,所以用樹鏈剖分將之轉換為線性結構。思路很簡單,重要是**實現。

#include

using

namespace std;

const

int maxn =

1e5+7;

typedef

long

long ll;

ll sum[maxn]

;int n, m;

int head[maxn]

, to[maxn<<1]

, nex[maxn<<1]

, tot =

2, edge[maxn<<1]

, hid;

struct node e[maxn]

;//給每一條邊編號

void

add(

int x,

int y,

int c)

intlowbit

(int i)

void

update

(int x,

int c)

}void

update_

(int x,

int y,

int c)

ll getsum

(int x)

int dfn[maxn]

, siz[maxn]

, dep[maxn]

, son[maxn]

, cnt, fa[maxn]

, top[maxn]

;ll dis[maxn]

;bool vis[maxn]

;void

dfs1

(int x,

int f)

//hid是剔除的邊

vis[v]

=true

; e[i>>1]

.id = i;

//給邊編號,因為是鏈式前向星存圖,i/2就是該邊的編號

dis[v]

= dis[x]

+ edge[i]

;//dis記錄改點到根的距離

dfs1

(v, x)

; siz[x]

+= siz[v];if

(siz[v]

> siz[son[x]

]) son[x]

= v;}}

}void

dfs2

(int x,

int fir)

}int

lca(

int x,

int y)

return dep[x]

> dep[y]

? y : x;

}ll cal

(int u,

int v)

intmain()

;}vis[1]

=true

;dfs1(1

,0);

dfs2(1

,1);

for(

int i =

1; i <= n; i++

)update_

(dfn[i]

, dfn[i]

, dis[i]);

while

(m--

)int dy = y - e[x]

.z;//這裡又是乙個轉換思想,修改權值等於增加差值

e[x]

.z = y;

update_

(dfn[to[e[x]

.id]

], dfn[to[e[x]

.id]

]+ siz[to[e[x]

.id]]-

1, dy)

;//區間修改要用差分思想,更新區間是該點和它的子樹

}else

}}

luogu P4949 最短距離

給出乙個 n 個點 n 條邊的無向連通圖。你需要支援兩種操作 修改 第 x 條邊的長度為 y 查詢 點 x 到點 y 的最短距離。共有 m 次操作。輸入格式 輸入共 n m 1 行 第 1 行,包含 2 個正整數 n,m,表示點數即邊數,操作次數。第 2 行到第 n 1 行,每行包含 3 個正整數 ...

1407 最短距離

兩個點 a b 均在做勻速直線運動。給出 t 0時刻 a b 的座標,以及 a b 的速度,計算t 0時兩個點的距離的最小值。輸入的第一行包含乙個整數 t 1 t 200 表示一共有 t 組測試資料。對於每組測試資料,第一行包含4個整數 x a y a v ax v ay 103 x a y a v...

編輯最短距離

給定兩個字串s和t,對於t我們允許三種操作 1 在任意位置新增任意字元 2 刪除存在的任意字元 3 修改任意字元 問最少操作多少次可以把字串t變成s?例如 s abcf t dbfg 那麼我們可以 1 把d改為a 2 刪掉g 3 加入c 所以答案是3。1 把t中字元全刪了,再新增s的全部字元,操作次...