題目傳送門(許可權題警告)
顯然可以發現,將1到i路徑上的最後一條路切斷後,需要重新找到一條從i的子樹出發的最短路徑重新回到最短路樹上去.
因此考慮一條邊什麼時候會被計算在答案中.
設一條邊u->v權值為val,只會可能對u,v到 lca(u,v) 之間的點產生影響.記錄源點1到節點i的距離為dep[i],那麼就可以把答案更新為dep[u]+dep[v]+val-dep[i]
.
可以預處理出dep,然後對於每一條邊都暴力爬公升至lca更新答案.
時間複雜度:o(n
m)
o(nm)
o(nm
)但是資料可能比較水,沒有生成最壞的資料卡,所以針對隨機資料是o(mlogn)
這樣做顯然不能過掉 (實際能過) ,於是開始優化.首先對於邊,按照dep[u]+dep[v]+val
排序,因為dep[i]是隨著點的不同有變化,不用管.
那麼顯然每個點有效的答案只會被第一次到它的邊更新.然後利用並查集,可以維護出乙個點u上次更新到的點.然後每次跳轉到那裡更新,注意判斷是否直接越過了lca.
時間複雜度:o(m
logm
)o(mlogm)
o(mlog
m)只寫了暴力,並查集**以後補
#include
#include
using
namespace std;
const
int maxn=
4005
;const
int maxm=
100005
;const
int inf=
0x3f3f3f3f
;int n,m,ncnt;
int p[maxn]
,dep[maxn]
,vis[maxn]
;int ans[maxn]
;int head[maxn]
,ecnt;
struct edgee[maxm]
;struct nodeg[maxm]
;void
addedge
(int u,
int v,
int val)
; head[u]
=ecnt;
}void
dfs(
int u,
int fa=0)
}int
main()
;}dfs(1)
;for
(int i=
1;i<=ncnt;i++
) g[i]
.val+
=dep[g[i]
.u]+dep[g[i]
.v];
for(
int i=
1;i<=n;i++
) ans[i]
=inf;
for(
int i=
1;i<=ncnt;i++)}
for(
int i=
2;i<=n;i++
)printf
("%s%d"
,i==2?
"":" ",ans[i]
==inf?-1
:ans[i]);
}
bzoj3694 最短路 樹鏈剖分
給出乙個n個點m條邊的無向圖,n個點的編號從1 n,定義源點為1。定義最短路樹如下 從源點1經過邊集t到任意一點i有且僅有一條路徑,且這條路徑是整個圖1到i的最短路徑,邊集t構成最短路樹。給出最短路樹,求對於除了源點1外的每個點i,求最短路,要求不經過給出的最短路樹上的1到i的路徑的最後一條邊。第一...
Bzoj 3694 最短路 樹鏈剖分
time limit 5 sec memory limit 256 mb submit 67 solved 34 submit status discuss 給出乙個n個點m條邊的無向圖,n個點的編號從1 n,定義源點為1。定義最短路樹如下 從源點1經過邊集t到任意一點i有且僅有一條路徑,且這條路徑...
BZOJ 3694 最短路 樹鏈剖分 倍增
下個月就是noip10連測試,還有什麼大學先修課考試,這段時間一直很忙但是還是抽出時間來複習一下版子,前段時間一直在搞spfa的各種建模,這段時間就來複習一下資料結構吧。首先就來不太好打的樹鏈剖分。嗯,開心,就每天寫一點點居然叫了兩遍就ac了,剛準備自己出資料還沒出,就抱著嘗試的想法提交了,居然ac...