[NOIP 2013]货车运输

想要求货车的最大载重量,根据木桶原理,我们就希望一条路径上的载重量的最小值最大。让一条路径上的载重量的最小值最大,贪心得想,如果我加进去的每条边都是剩余边中最大的那一个,那么在形成完整的通路时,一条路径上的边一定是所有情况中最大的那一种,这个思想很明显就是最大生成树。

LCA找路径求最小值就好了。

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstdio>
  4 using namespace std;
  5 const int maxn=1e5+10;
  6 const int inf=1e9;
  7 int n,m;
  8 struct edge{
  9     int to,next,w;
 10 }ed[maxn];
 11 struct node{
 12     int x,y,dis;
 13 }pos[maxn];
 14 int head[maxn],tot;
 15 void add(int u,int to,int w){
 16     ed[++tot].w=w;
 17     ed[tot].to=to;
 18     ed[tot].next=head[u];
 19     head[u]=tot;
 20 }
 21 int fa[maxn];
 22 void init(){
 23     for(int i = 1;i <= n;i++) fa[i]=i;
 24 }
 25 int find(int x){
 26     if (fa[x]==x) return x;
 27     else return fa[x]=find(fa[x]);
 28 }
 29 void update(int x,int y){
 30     int fx=find(x),fy=find(y);
 31     fa[fx]=fy;
 32 }
 33 bool cmp(node x,node y){
 34     return x.dis>y.dis;
 35 }
 36 void tree(){
 37     sort(pos+1,pos+m+1,cmp);
 38     init();
 39     for (int i = 1;i <= m;i++){
 40         int x=pos[i].x,y=pos[i].y,w=pos[i].dis;
 41         if (find(x)!=find(y)){
 42             update(find(x),find(y));
 43             add(x,y,w);add(y,x,w);
 44         }
 45     }
 46 }
 47 int vis[maxn],dep[maxn],w[maxn][30],f[maxn][30];
 48 void dfs(int x){
 49     vis[x]=1;
 50     for (int i = head[x];i;i=ed[i].next){
 51         int to=ed[i].to;
 52         if (vis[to]) continue;
 53         dep[to]=dep[x]+1;
 54         f[to][0]=x;
 55         w[to][0]=ed[i].w;
 56         dfs(to);
 57     }
 58 }
 59 int lca(int x,int y){
 60     if (find(x)!=find(y)) return -1;
 61     int ans=inf;
 62     if (dep[x]>dep[y]) swap(x,y);
 63     for (int i = 20;i >= 0;i--){
 64         if (dep[f[y][i]]>=dep[x]){
 65             ans=min(ans,w[y][i]);
 66             y=f[y][i];
 67         }
 68     }
 69     if (x==y) return ans;
 70     for (int i = 20;i>= 0;i--){
 71         if (f[x][i]!=f[y][i]){
 72             ans=min(ans,min(w[x][i],w[y][i]));
 73             x=f[x][i];
 74             y=f[y][i];
 75         }
 76     }
 77     ans=min(ans,min(w[x][0],w[y][0]));
 78     return ans;
 79 }
 80 int main(){
 81     int x,y,z,q;
 82     scanf ("%d%d",&n,&m);
 83     for (int i = 1;i <= m;i++){
 84         scanf ("%d%d%d",&x,&y,&z);
 85         pos[i].x=x,pos[i].y=y,pos[i].dis=z;
 86     }
 87     tree();
 88     for (int i = 1;i <= n;i++){
 89         if (!vis[i]){
 90             dep[i]=1;
 91             dfs(i);
 92             f[i][0]=i;
 93             w[i][0]=inf;
 94         }
 95     }
 96     for (int i= 1;i <= 20;i++){
 97         for (int j = 1;j <= n;j++){
 98             f[j][i]=f[f[j][i-1]][i-1];
 99             w[j][i]=min(w[j][i-1],w[f[j][i-1]][i-1]);
100         }
101     }
102     scanf ("%d",&q);
103     for (int i = 1;i <= q;i++){
104         scanf ("%d%d",&x,&y);
105         printf("%d\n",lca(x,y));
106     }
107     return 0;
108 }

 另一道题UVA11354 Bond就是反过来,求最小生成树,LCA求最大值

 

posted @ 2020-09-23 10:32  小又又  阅读(201)  评论(0编辑  收藏  举报