1. 程式人生 > >Luogu P1967 貨車運輸

Luogu P1967 貨車運輸

con display color nbsp div i++ head hid tdi

qwq

這題是知道了正解做法才寫的..

求每兩點間最小權值最大的路徑,本來我以為要每個點都跑一遍dij(?),後來意識到生成樹好像是用來找這個的( ′▽`)

然後我問dtxdalao對不對,他說“我記得這道題好像要用倍增”(我:???劇透會被關進小黑屋的)

其實就是最大生成樹是隨便建的,然後對於每兩點,用倍增求他們的lca,沿途更新最小的邊權即為答案

其實我也沒怎麽debug i--這種問題就不說了吧)

這題思路還算比較清晰,明白做法之後就分別把幾個算法寫出來就行了,

註意:lca中最小邊權的更新可能在跳到深度相同/同時倍增/最後求lca的路上,所以...反正多更新幾次就沒錯啦w

技術分享圖片
#include<cstdio>
#include
<algorithm> #include<cmath> #define MogeKo qwq using namespace std; const int maxn = 100005; int n,m,q,x,y; int cnt,head[maxn],to[maxn],nxt[maxn],val[maxn]; int fa[maxn],dpth[maxn],p[maxn][25],w[maxn][25]; void add(int x,int y,int z) { to[++cnt] = y; nxt[cnt] = head[x]; head[x]
= cnt; val[cnt] = z; } struct edg { int l,r,c; } a[maxn]; bool cmp(edg A,edg B) { return A.c > B.c; } int getfa(int x) { if(fa[x] == x)return x; else return fa[x] = getfa(fa[x]); } void kruskal() { sort(a+1,a+m+1,cmp); for(int i = 1; i <= m; i++) { int xx = getfa(a[i].l);
int yy = getfa(a[i].r); if(xx == yy)continue; fa[xx] = yy; add(xx,yy,a[i].c); add(yy,xx,a[i].c); } } void dfs(int u,int fa) { for(int i = 1; (1 << i) <= dpth[u]; i++) { p[u][i] = p[p[u][i-1]][i-1]; w[u][i] = min(w[u][i-1],w[p[u][i-1]][i-1]); } for(int i = head[u]; i; i = nxt[i]) { int v = to[i]; if(v == fa)continue; dpth[v] = dpth[u]+1; p[v][0] = u; w[v][0] = val[i]; dfs(v,u); } } int lca(int a,int b) { int ans = 2147483647; if(dpth[a] < dpth[b]) swap(a,b); for(int i = log2(dpth[a]); i >= 0; i--) if(dpth[p[a][i]] >= dpth[b]) { ans = min(ans,w[a][i]); a = p[a][i]; } if(a == b)return ans; for(int i = log2(dpth[a]); i >= 0; i--) if(p[a][i] != p[b][i]) { ans = min(ans,min(w[a][i],w[b][i])); a = p[a][i]; b = p[b][i]; } ans = min(ans,min(w[a][0],w[b][0])); return ans; } int main() { scanf("%d%d",&n,&m); for(int i = 1; i <= n; i++) fa[i] = i; for(int i = 1; i <= m; i++) scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].c); kruskal(); for(int i = 1; i <= n; i++) if(fa[i] == i){ dpth[i] = 1; dfs(i,0); } scanf("%d",&q); while(q--) { scanf("%d%d",&x,&y); int xx = getfa(x); int yy = getfa(y); if(xx != yy) { printf("-1\n"); continue; } printf("%d\n",lca(x,y)); } return 0; }
View Code

Luogu P1967 貨車運輸