[2019 CSP-S赛前集训] [洛谷P1967] 货车运输

题目链接:https://www.luogu.org/problem/P1967

题目意思大概是要求路径的最小权值的最大值,我们可以将权值小的无关紧要的边去掉;

方法可以使用最大生成树重新建图,然后再最大生成树上用LCA来回答每一个询问.

这里博主使用倍增求LCA的,当时太菜了,没想到用倍增直接来存权值,就通过每个点的fa数组来求到LCA路径上的最小权值;

  1 #include <bits/stdc++.h>
  2 #define N 100000+5
  3 #define M 500000+5
  4 using namespace std;
  5 struct node
  6 {
  7     int u,v,wei;
  8 }a[M];
  9 int n,m,lgn,q;
 10 int ans;
 11 int f[N][25],fa[N],vis[N],depth[N],fw[N];
 12 vector <int> edge[N],w[N],wn[N];
 13 bool cmp(node a,node b)
 14 {
 15     return a.wei>b.wei;
 16 }
 17 int Find(int u)
 18 {
 19     while(u!=fa[u])
 20     {
 21         fa[u]=fa[fa[u]];
 22         u=fa[u];
 23     }
 24     return u;
 25 }
 26 void Kruskal()//求最大生成树
 27 {
 28     for(int i=1;i<=m;i++)
 29     {
 30         int u=a[i].u,v=a[i].v,wei=a[i].wei;
 31         int fau=Find(u),fav=Find(v);
 32         if(fau!=fav)
 33         {
 34             fa[fau]=fav;
 35             edge[u].push_back(v);
 36             w[u].push_back(wei);
 37             edge[v].push_back(u);
 38             w[v].push_back(wei);
 39         }
 40     }
 41 }
 42 void dfs(int u)
 43 {
 44     vis[u]=1;
 45     for(int i=0;i<edge[u].size();i++)
 46     {
 47         int now=edge[u][i];
 48         if(!vis[now])
 49         {
 50             f[now][0]=u;
 51             depth[now]=depth[u]+1;
 52             fw[now]=w[u][i];
 53             dfs(now);
 54         }
 55     }
 56 }
 57 void getfather()//倍增
 58 {
 59     for(int j=1;j<=lgn;j++)
 60     {    
 61         for(int i=1;i<=n;i++)
 62         {
 63             f[i][j]=f[f[i][j-1]][j-1];
 64         }
 65     }
 66 }
 67 int LCA(int u,int v)//LCA模板
 68 {
 69     if(depth[u]<depth[v]) swap(u,v);
 70     int dist=depth[u]-depth[v];
 71     int j=0;
 72     while(dist)
 73     {
 74         if(dist&1) u=f[u][j];
 75         dist>>=1;
 76         j++;
 77     }
 78     if(u==v) return u;
 79     for(int j=lgn-1;j>=0;j--)
 80     {
 81         if(f[u][j]!=f[v][j])
 82         {
 83             u=f[u][j];
 84             v=f[v][j];
 85         }
 86     }
 87     return f[u][0];
 88 }
 89 void work(int u,int com)//求到LCA路径上的最小权值
 90 {
 91     while(u!=com)
 92     {
 93         int nxt=f[u][0];
 94         ans=min(ans,fw[u]);
 95         u=nxt;
 96     }
 97 }
 98 int main()
 99 {
100     scanf("%d%d",&n,&m);
101     lgn=log2(n);
102     for(int i=1;i<=m;i++)
103     {
104         scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].wei);
105     }
106     for(int i=1;i<=n;i++) fa[i]=i;
107     sort(a+1,a+m+1,cmp);
108     Kruskal();
109     for(int i=1;i<=n;i++)
110     {
111         if(!vis[i]) dfs(i);
112     }
113     getfather();
114     scanf("%d",&q);
115     for(int i=1;i<=q;i++)
116     {
117         ans=INT_MAX;
118         int u,v;
119         scanf("%d%d",&u,&v);
120         int lca=LCA(u,v);
121         work(u,lca);
122         work(v,lca);
123         if(lca==0)printf("-1\n");
124         else printf("%d\n",ans);
125     }
126     return 0;
127 }

 

posted @ 2019-10-18 21:59  Xx_queue  阅读(128)  评论(0编辑  收藏  举报