給出乙個 n 個點 n 條邊的無向連通圖。
你需要支援兩種操作:
修改 第 x 條邊的長度為 y ;
查詢 點 x 到點 y 的最短距離。
共有 m 次操作。
輸入格式:
輸入共 n + m + 1 行:
第 1 行,包含 2 個正整數 n,m,表示點數即邊數,操作次數。
第 2 行到第 n + 1 行,每行包含 3 個正整數 x,y,z,表示 x 與 y 間有一條長度 為 z 的邊。
第 n + 2 到 n + m + 1 行,每行包含 3 個正整數 opt,x,y,表示操作種類,操作的引數(含義見【題目描述】)。
輸出格式:
對於每次操作 2 輸出查詢的結果。
此題是一道基環樹上樹鏈剖分題目
思路是這樣的:基環樹其實可以看做一棵樹多連了一條邊,於是我們可以通過加邊時維護乙個並查集,來找出多的那條邊。
將那條多出的邊記錄下來。
然後我們考慮u到v的最大值,有兩種情況
u直接在樹上到v
u,v到多出的那條邊的兩端,通過這條邊連在一起
與是我們就可以很愉快的在樹上跑樹鏈剖分了,注意此題是邊權而不是點權
那我們對於u到v權值為w的一條邊可以看做u->xx->v,u,v點權為0,xx點權為w,就可將邊權轉化為點權了,點數翻倍,記得陣列大小翻倍喲
值得一提的是我一開始線段樹的陣列忘記開4倍了,結果又wa又tle40分,搞得我還以為**寫錯了呢
實現如下:
#include #include#include
#include
#include
#include
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
using
namespace
std;
typedef
long
long
ll;inline
intread()
const
int n=200100
;int n,q,op,u,v,w,cnt,sum[n<<2],head[n],top[n],fe[n],fa[n],id[n],dep[n],size[n],son[n],ww[n],wn[n],tim=0
,t1,t2,keu,kev,kew,kex,xu;
int getf(int u)
struct edgee[n<<1
];void add(int u,int v);head[u]=cnt;}
void build(int l,int r,int
o)
int mid=(l+r)>>1
; build(lson);build(rson);
sum[o]=sum[o<<1]+sum[o<<1|1];}
void update(int pre,int val,int l,int r,int
o)
int mid=(l+r)>>1
;
if(pre<=mid) update(pre,val,lson);
else
update(pre,val,rson);
sum[o]=sum[o<<1]+sum[o<<1|1];}
int query(int l,int r,int l,int r,int
o)int query_tree(int u,int
v)
if(dep[u]>dep[v]) swap(u,v);
return ans+query(id[u],id[v],1,n,1);}
void dfs1(int u,int
ff)}
void dfs2(int u,int
topf)
intmain()
else }n
<<=1
; dfs1(
1,1);dfs2(1,1);build(1,n,1
);
int ans=0
;
while(q--)
else
}return0;
}
洛谷P4949 最短距離
給出乙個 n 個點 n 條邊的無向連通圖。你需要支援兩種操作 修改 第 x 條邊的長度為 y 查詢 點 x 到點 y 的最短距離。共有 m 次操作。思路 n個點n條邊的無向連通圖 簡單圖 如果少一條邊就是形成一棵樹,就是一道lca題,這題多了一條邊,就要用相應的方法處理這條邊。考慮剔除的邊是 uu,...
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的全部字元,操作次...