YbtOJ 631 次短路徑 左偏樹,最短路

2022-03-29 04:25:28 字數 1297 閱讀 4183

給出\(n\)個點\(m\)條邊的一張無向圖,對於每個點\(i\)求不經過\(i\sim 1\)的最短路的第一條邊的情況下\(i\)到\(1\)的最短路

資料保證這條邊唯一

\(n\in[1,10^5],m\in[1,2\times 10^5],c\in[1,10^3]\)

因為保證的那個東西,所以圖的最短路樹真的是一棵樹了,所以先跑出最短路樹考慮在最短路樹上面搞。

然後題目限制了我們不能從樹上的祖先那條邊過來,這樣就分為了兩種情況。一種是從該點的子樹外面連過來的邊,另一種是從子樹中走上來的邊。第二種很麻煩,因為子樹的最短路是用該節點的最短路擴充套件的,所以不能直接使用。

考慮一條非樹邊\((x,y)\),這條邊會擴充套件一條\(dis_y+w\)到\(x\)的路徑。(\(dis_x\)表示\(1\sim x\)的最短路)。

並且這條邊可以使用到\(lca(x,y)\)處,此時\(x\)的祖先們都不包含\(y\)在子樹內,可以直接用\(y\)的子樹擴充套件。

所以可以維護乙個左偏樹,每次合併兩個兒子的資訊,如果堆頂的邊需要被刪除就刪除。需要寫乙個\(lazy\)標記來修改整棵樹

時間複雜度\(o(n\log n)\)

#include#include#include#include#include#define mp(x,y) make_pair(x,y)

using namespace std;

const int n=4e5+10;

struct point

};bool operator<(point x,point y)

int del(int x)

}t;struct nodea[n];

int n,m,tot,cnt,num,ls[n],f[n];

int rfn[n],p[n],ans[n];

bool v[n];vectorg[n];

priority_queue>q;

void addl(int x,int y,int w)

void dij()

ans[x]=w.val;break;

} return;

}int main()

dij();

for(int x=1;x<=n;x++)

for(int i=ls[x];i;i=a[i].next)

dfs(1);

for(int i=2;i<=n;i++)

if(!ans[i])puts("-1");

else printf("%d\n",ans[i]);

return 0;

}

最短路徑樹

問題描述 所謂最短路徑樹,就是從s出發,沿著樹上的邊走到任意點i,那麼經過的這些邊的權值和就是s到i的最短路徑。dijkstra演算法或spfa演算法不僅可計算從起點s到各點的最短路徑長度,同時也可得到以s為根的最短路徑樹。方法是在進行鬆弛操作時,如果d i c d j 時,除了更新d j 之外,還...

最短路徑,最短路徑樹和最小生成樹

首先介紹這三個概念,很多人都聽過最短路徑了,但是最短路徑樹卻很少聽過,關於最短路徑樹的介紹也不太多。而最短路徑樹和最小生成樹更是完全不同的兩個概念。最短路徑就是從乙個指定的頂點出發,計算從該頂點出發到其他所有頂點的最短路徑。通常用dijkstra演算法,floyd演算法求解。最短路徑樹spt sho...

SPF(最短路徑樹)演算法

構造一棵樹 a 使n個節點之間的總長最小 樹是乙個在每兩個節點之間僅有一條路徑的圖 在我們給出構造過程中,分支被分成3個集合 被明確分配給構造中的樹的分支 他們將在子樹中 這個分支的隔壁分枝被新增到集合1 剩餘的分支 拋棄或不考慮 節點被分成兩個集合 a 被集合1中的分支連線的節點 b 剩餘的節點 ...