NOIP 2013 提高组 洛谷P1967 货车运输 (Kruskal重构树)
Posted ynhnxn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP 2013 提高组 洛谷P1967 货车运输 (Kruskal重构树)相关的知识,希望对你有一定的参考价值。
题目:
A 国有 nn 座城市,编号从 11 到 nn,城市之间有 mm 条双向道路。每一条道路对车辆都有重量限制,简称限重。
现在有 qq 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
对于每一组询问,相当于求点x到点y中所有路径中最小边权的最大值,这样就是货车的最大载重。
那么这显然可以用Kruskal重构树来解决,将重构树建成大根堆,就可以求最大边权的最小值;同理,小根堆就是最小边权的最大值。
那么做这道题就是重构树的模板题了。复杂度O(q logn)。
#include<bits/stdc++.h> using namespace std; const int N=2e5+10; struct edge int u,v,w; bool operator < (const edge &x) return w>x.w; //小根堆 e[N]; vector<int> g[N]; int n,m,q,cnt,fa[N],vis[N],val[N],d[N],f[N][30]; int find(int x) return fa[x]==x?fa[x]:fa[x]=find(fa[x]); void kruskal() sort(e+1,e+m+1); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) int fu=find(e[i].u),fv=find(e[i].v); if(fu!=fv) val[++cnt]=e[i].w; fa[cnt]=fa[fu]=fa[fv]=cnt; g[cnt].push_back(fu); g[cnt].push_back(fv); g[fu].push_back(cnt); g[fv].push_back(cnt); void dfs(int u,int fa) d[u]=d[fa]+1,f[u][0]=fa,vis[u]=1; for(int i=1;(1<<i)<=d[u];i++) f[u][i]=f[f[u][i-1]][i-1]; for(int i=0;i<g[u].size();i++) int v=g[u][i]; if(v!=fa) dfs(v,u); int lca(int x,int y) if(d[x]<d[y]) swap(x,y); for(int i=25;i>=0;i--) if(d[f[x][i]]>=d[y]) x=f[x][i]; if(x==y) return x; for(int i=25;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0]; int main() scanf("%d%d",&n,&m); cnt=n; for(int i=1;i<=m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); kruskal(); for(int i=1;i<=cnt;i++)//注意图可能是个森林,不要漏掉 if(!vis[i]) int f=find(i); dfs(f,0); scanf("%d",&q); while(q--) int u,v; scanf("%d%d",&u,&v); if(find(u)!=find(v)) cout<<-1<<endl; else cout<<val[lca(u,v)]<<endl; return 0;
以上是关于NOIP 2013 提高组 洛谷P1967 货车运输 (Kruskal重构树)的主要内容,如果未能解决你的问题,请参考以下文章
[luogu P1967][NOIp2013]P1967 货车运输