BZOJ 3694 最短路 樹鏈剖分 倍增

2021-07-23 02:53:03 字數 2764 閱讀 8116

下個月就是noip10連測試,還有什麼大學先修課考試,這段時間一直很忙但是還是抽出時間來複習一下版子,前段時間一直在搞spfa的各種建模,這段時間就來複習一下資料結構吧。首先就來不太好打的樹鏈剖分。

嗯,開心,♪(^∀^●)ノ,就每天寫一點點居然叫了兩遍就ac了,剛準備自己出資料還沒出,就抱著嘗試的想法提交了,居然ac了,哈哈。

傳送門似乎是許可權題

description

給出乙個n個點m條邊的無向圖,n個點的編號從1~n,定義源點為1。定義最短路樹如下:從源點1經過邊集t到任意一點i有且僅有一條路徑,且這條路徑是整個圖1到i的最短路徑,邊集t構成最短路樹。 給出最短路樹,求對於除了源點1外的每個點i,求最短路,要求不經過給出的最短路樹上的1到i的路徑的最後一條邊。

input

第一行包含兩個數n和m,表示圖中有n個點和m條邊。

接下來m行,每行有四個數ai,bi,li,ti,表示圖中第i條邊連線ai和bi權值為li,ti為1表示這條邊是最短路樹上的邊,ti為0表示不是最短路樹上的邊。

output

輸出n-1個數,第i個數表示從1到i+1的要求的最短路。無法到達輸出-1。

sample input

5 9

3 1 3 1

1 4 2 1

2 1 6 0

2 3 4 0

5 2 3 0

3 2 2 1

5 3 1 1

3 5 2 0

4 5 4 0

sample output

6 7 8 5
hint

對於100%的資料,n≤4000,m≤100000,1≤li≤100000

題解:

這個題目,首先按照題目給的建出最短路徑樹,若我們不經過最後的一條邊那麼我們一定是先往下走然後再往上走最後到點1;這兒如果是想不清楚就畫出題目中的要求就自己畫個圖來輔助理解一下。

然後我們把非最短路上的邊取出來,

假設有這樣一條邊 u - v 權值為c

那麼我們計算出lca(u,v) = t

我們從1到u,再從u經過這個邊到v,然後在所有的從t-v上的邊滿足要求的到1的距離為d[u] + d[v] - d[x] + c;

我們只要對每一條邊都這樣不斷更新每個點的距離最可以啦。

**:

#include 

#include

#include

const int maxn = 4005,maxx = 100005,maxd = 20,inf = 1e6;

using namespace std;

int n,m,e = 1,e1 = 1,dfn = 1,dx,dy,dt,ql,qr,data;

int head[maxn],s[maxn],anc[maxn][maxd+5],c[maxn],min[maxn*20];

inline int min(int a,int b)

struct slpff[maxn];

struct nodeedge[10

*maxx];

struct fnodeedge1[10

*maxx];

inline int

read()

while('0'

<= ch && ch <='9')

returnx;}

inline void addedge(int u,int v,int c);head[u] = e++;

}inline void init();

}}void dfs(int u)

}}void dfs_1(int u,int h)

}}void dfs_2(int u,int top)

for(int i = head[u];i;i = edge[i].next)

}}inline void swim(int &u,int h)

h >>= 1;

}}inline int lca(int

x,int

y) if(x != y) return anc[x][0];

else

returnx;}

inline void maintain(int o)

void update(int o,int l,int r)

if(ql <= mid) update(o*2,l,mid);

if(qr > mid) update(o*2+1,mid+1,r);

}void update_inf(int o,int l,int r)

intprint(int o,int l,int r)

if(ql <= mid) return

print(o*2,l,mid);

else

return

print(o*2+1,mid+1,r);

}inline void query(int

x,int

y) else

}if(f[x].deep < f[y].deep)

else

}int main()

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

return

0;}

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有且僅有一條路徑,且這條路徑...

bzoj3694 最短路 樹鏈剖分 線段樹

最短路 bzoj 3694 題目大意 給你乙個n個點m條邊的無向圖,源點為1,並且以點1為根給出最短路樹。求對於2到n的每個點i,求最短路,要求不經過給出的最短路樹上的1到i的路徑上的最後一條邊。注釋 1 le n le 4000 1 le m le 10 5 想法 對於任意兩個點u和v,滿足u和v...