time limit: 5 sec memory limit: 256 mb
submit: 67 solved: 34
[submit][status][discuss]
給出乙個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
題解:首先,先處理出最短路樹中每個點i距源點1的最短距離dis[i]。
因為要求不經過最短路樹的最後一條邊,所以要到乙個點,必須要從和這個點在同乙個環中的另外一邊繞過去。
例如:設我們要到u點,我們還有不在最短路樹上的兩個點x,y。t為lca(x,y)。假如u點在y到t的路徑上,我們既然不能從1經過t到u,那我們只有從1 -> t -> x -> y ->u。這樣我們可以用dis[x]+val[x][y]+dis[y]-dis[u]來更新ans。因為dis[u]是不變的,所以我們可以最後去減去dis[u]。之前只用維護dis[x]+val[x][y]+dis[y]即可。
1 #include2using
namespace
std;
3#define maxn 4010
4#define maxm 100010
5#define inf 1e9
6struct
node
7edge[maxn*2
];10
struct
node
11tree[maxn*5
];14
int cnt,head[maxn],n,size[maxn],deep[maxn],p[maxn][12
],dis[maxn],pos[maxn],belong[maxn],s1[maxm],s2[maxm],s3[maxm],size;
15bool
vis[maxn];
16void addedge(int bb,int ee,int
vv)17
20void addedge1(int bb,int ee,int
vv)21
24int
read()
2528
while(ch>='
0'&&ch<='9')
29return s*fh;30}
31void dfs1(int
u)3246}
47}48void
ycl()
4957}58
}59void dfs2(int u,int
chain)
6068
if(k==0)return;69
dfs2(k,chain);
70for(i=head[u];i!=-1;i=edge[i].next)
7175}76
int lca(int x,int
y)7790}
91return p[x][0
];92}93
void build(int k,int l,int
r)94
97int mid=(l+r)/2
;98 build(k*2
,l,mid);
99 build(k*2+1,mid+1
,r);
100}
101void pushup(int
k)102
106void pushdown(int
k)107
117}
118void change(int k,int l,int r,int
c)119
121pushdown(k);
122int mid=(tree[k].left+tree[k].right)/2
;123
if(r<=mid)change(k*2
,l,r,c);
124else
if(l>mid)change(k*2+1
,l,r,c);
125else
126pushup(k);
127}
128void solve_change(int x,int f,int
c)129
135if(x!=f)change(1,pos[f]+1
,pos[x],c);
136}
137int query(int k,int l,int
r)138
146int solve_query(int x,int
f)147
154if(x!=f)mn=min(mn,query(1,pos[f]+1
,pos[x]));
155return
mn;156
}157
int ask(int k,int
lr)158
165int
main()
166178
else
addedge1(a,b,l);
179}
180 memset(p,-1,sizeof(p));size=0
;181 dfs1(1
);ycl();
182 dfs2(1,1
);183 build(1,1
,n);
184//
for(i=1;i<=n;i++)change(1,pos[i],pos[i],dis[i]);
185for(i=1;i<=tot;i++)
186192
for(i=2;i<=n;i++)
193200
return0;
201 }
bzoj3694 最短路 樹鏈剖分
給出乙個n個點m條邊的無向圖,n個點的編號從1 n,定義源點為1。定義最短路樹如下 從源點1經過邊集t到任意一點i有且僅有一條路徑,且這條路徑是整個圖1到i的最短路徑,邊集t構成最短路樹。給出最短路樹,求對於除了源點1外的每個點i,求最短路,要求不經過給出的最短路樹上的1到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...