zoukankan      html  css  js  c++  java
  • 【NOIP2013】货车运输 最大生成树+倍增

    题目大意:给你一张n个点m条边的图,有q次询问,每次让你找出一条从x至y的路径,使得路径上经过的边的最小值最大,输出这个最大的最小值。

    显然,经过的路径必然在这张图的最大生成树上。

    我们求出这个图的最大生成树后,用st表维护最小值,然后随便倍增下就好了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<vector>
     6 #include<algorithm>
     7 #include<set>
     8 #include<map>
     9 #include<queue>
    10 #define M 100005
    11 #define INF 19260817
    12 using namespace std;
    13 
    14 int f[M][20]={0},minn[M][20]={0},dep[M]={0},vis[M]={0};
    15 struct edge{int u,v,next;}e[M*2]={0}; int head[M]={0},use=0;
    16 void dfs(int x,int fa,int v){
    17     vis[x]=1; f[x][0]=fa; dep[x]=dep[fa]+1; minn[x][0]=v;
    18     for(int i=1;i<20;i++) 
    19     f[x][i]=f[f[x][i-1]][i-1],minn[x][i]=min(minn[x][i-1],minn[f[x][i-1]][i-1]);
    20     for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa) dfs(e[i].u,x,e[i].v);
    21 }
    22 int getmin(int x,int y){
    23     if(dep[x]<dep[y]) swap(x,y); int res=INF,cha=dep[x]-dep[y];
    24     for(int i=19;~i;i--) if(cha&(1<<i)) res=min(res,minn[x][i]),x=f[x][i];
    25     for(int i=19;~i;i--) if(f[x][i]!=f[y][i]) res=min(res,min(minn[x][i],minn[y][i])),x=f[x][i],y=f[y][i];
    26     if(x==y) return res; return min(res,min(minn[x][0],minn[y][0]));
    27 }
    28 
    29 struct bian{
    30     int x,y,z; bian(){x=y=z=0;}
    31     friend bool operator <(bian a,bian b){return a.z<b.z;}
    32 }a[M];
    33 void add(int x,int y,int z){use++;e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use;}
    34 int fa[M]={0};int get(int x){return fa[x]==x?x:fa[x]=get(fa[x]);}
    35 
    36 int main(){
    37     memset(minn,1,sizeof(minn));
    38     int n,m; scanf("%d%d",&n,&m);
    39     for(int i=1;i<=n;i++) fa[i]=i;
    40     for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
    41     sort(a+1,a+m+1);
    42     for(int i=m;i;i--){
    43         int x=get(a[i].x),y=get(a[i].y);
    44         if(x==y) continue;
    45         add(a[i].x,a[i].y,a[i].z);
    46         add(a[i].y,a[i].x,a[i].z);
    47         fa[x]=y;
    48     }
    49     for(int i=1;i<=n;i++)
    50     if(!vis[i]) dfs(i,0,INF);
    51     int q; scanf("%d",&q);
    52     while(q--){
    53         int x,y; scanf("%d%d",&x,&y);
    54         if(get(x)!=get(y)) printf("-1
    ");
    55         else printf("%d
    ",getmin(x,y));
    56     }
    57 }
  • 相关阅读:
    等宽布局和flex
    antd按需加载
    linux-redis cluster集群(redis5.x)
    linux-mysql-主从同步
    mysql-行转列
    Spring Bean 作用域
    ArrayList、LinkedList区别(jdk8)
    java类及实例初始化顺序
    线程池-结构
    GIT基础
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/9745995.html
Copyright © 2011-2022 走看看