其他分享
首页 > 其他分享> > NOIP 2013 提高组 洛谷P1967 货车运输 (Kruskal重构树)

NOIP 2013 提高组 洛谷P1967 货车运输 (Kruskal重构树)

作者:互联网

题目:

A 国有 nn 座城市,编号从 11 到 nn,城市之间有 mm 条双向道路。每一条道路对车辆都有重量限制,简称限重。

现在有 qq 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

 

 

对于每一组询问,相当于求点x到点y中所有路径中最小边权的最大值,这样就是货车的最大载重。

那么这显然可以用Kruskal重构树来解决,将重构树建成大根堆,就可以求最大边权的最小值;同理,小根堆就是最小边权的最大值。

那么做这道题就是重构树的模板题了。复杂度O(q logn)。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=2e5+10;
 4 struct edge{
 5     int u,v,w;
 6     bool operator < (const edge &x){
 7         return w>x.w;    //小根堆 
 8     }
 9 }e[N];
10 vector<int> g[N];
11 int n,m,q,cnt,fa[N],vis[N],val[N],d[N],f[N][30];
12 int find(int x){
13     return fa[x]==x?fa[x]:fa[x]=find(fa[x]);
14 }
15 
16 void kruskal(){
17     sort(e+1,e+m+1);
18     for(int i=1;i<=n;i++) fa[i]=i;
19     for(int i=1;i<=m;i++){
20         int fu=find(e[i].u),fv=find(e[i].v);
21         if(fu!=fv){
22             val[++cnt]=e[i].w;
23             fa[cnt]=fa[fu]=fa[fv]=cnt;
24             g[cnt].push_back(fu);
25             g[cnt].push_back(fv);
26             g[fu].push_back(cnt);
27             g[fv].push_back(cnt);
28         }
29     }
30 }
31 
32 void dfs(int u,int fa){
33     d[u]=d[fa]+1,f[u][0]=fa,vis[u]=1;
34     for(int i=1;(1<<i)<=d[u];i++)
35         f[u][i]=f[f[u][i-1]][i-1];
36     for(int i=0;i<g[u].size();i++){
37         int v=g[u][i];
38         if(v!=fa) dfs(v,u);
39     }
40 }
41 
42 int lca(int x,int y){
43     if(d[x]<d[y]) swap(x,y);
44     for(int i=25;i>=0;i--)
45         if(d[f[x][i]]>=d[y]) x=f[x][i];
46     if(x==y) return x;
47     for(int i=25;i>=0;i--)
48         if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
49     return f[x][0];
50 }
51 
52 int main(){
53     scanf("%d%d",&n,&m);
54     cnt=n;
55     for(int i=1;i<=m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
56     kruskal();
57     for(int i=1;i<=cnt;i++){//注意图可能是个森林,不要漏掉 
58         if(!vis[i]){
59             int f=find(i);
60             dfs(f,0);
61         }
62     }
63     scanf("%d",&q);
64     while(q--){
65         int u,v;
66         scanf("%d%d",&u,&v);
67         if(find(u)!=find(v)) cout<<-1<<endl;
68         else cout<<val[lca(u,v)]<<endl;
69     }
70     return 0;
71 }

 

标签:重构,洛谷,NOIP,int,边权,货车运输,fa,return,find
来源: https://www.cnblogs.com/yhxnoerror/p/16100110.html