給出乙個n個點m條邊的無向圖,n個點的編號從1~n,定義源點為1。定義最短路樹如下:從源點1經過邊集t到任意一點i有且僅有一條路徑,且這條路徑是整個圖1到i的最短路徑,邊集t構成最短路樹。
給出最短路樹,求對於除了源點1外的每個點i,求最短路,要求不經過給出的最短路樹上的1到i的路徑的最後一條邊。
第一行包含兩個數n和m,表示圖中有n個點和m條邊。
接下來m行,每行有四個數ai,bi,li,ti,表示圖中第i條邊連線ai和bi權值為li,ti為1表示這條邊是最短路樹上的邊,ti為0表示不是最短路樹上的邊。
輸出n-1個數,第i個數表示從1到i+1的要求的最短路。無法到達輸出-1。
5 93 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
6 7 8 5
對於100%的資料,n≤4000,m≤100000,1≤li≤100000
題解:首先建出最短路徑樹。
對於一條不在最短路徑樹里的邊,
設該邊的兩端點為x,y.t為x和y的最近公共祖先,dis[i]表示1到i的最短距離.
那麼對於x和t之間的點u,一定存在1-t-y-x-u的路徑。路徑長度為d[y]+v(x,y)+d[x]-d[u].
我們需要最小化d[x]+d[y]+v(x,y).y和t之間的點同理。
所以我們列舉每一條不在最短路徑樹里的邊.更新兩端點和lca之間的點即可。
這些顯然可以用樹鏈剖分解決。
**:
#include#include#include#define n 100010
int pos[n],bl[n],point[n],next[n],t[n*4],p[n*4],size[n];
int f,cnt,num,sz,n,m,x,y,w,fa[n][20],dis[n],deep[n];
struct usee[n];
struct use2b[n];
using namespace std;
void add(int x,int y,int w)
void dfs(int x)
int lca(int x,int y)
void paint(int k,int v)
void pushdown(int k,int v)
void add(int k,int l,int r,int ll,int rr,int v)
if (ll<=mid) add(k<<1,l,mid,ll,rr,v);
if (rr>mid) add(k<<1|1,mid+1,r,ll,rr,v);
t[k]=min(t[k<<1],t[k<<1|1]);
}int ask(int k,int l,int r,int x)
void solveadd(int x,int y,int v)
if (x!=y) add(1,1,sz,pos[y]+1,pos[x],v);
}void solve()
for (int i=2;i<=n;i++)
}int main()
dfs(1),dfs2(1,1);solve();
}
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...
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...