p1967 货车运输

传送门

题目

A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

输入格式:

输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。

接下来 m 行每行 3 个整数 x、 y、 z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意: x 不等于 y,两座城之间可能有多条道路

接下来一行有一个整数 q,表示有 q 辆货车需要运货。

接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意: x 不等于 y

输出格式:

输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货

车不能到达目的地,输出-1。

分析

首先,因为我们要让最小边权最大,所以一些较小边是我们不需要的,因此我们要先建一棵最大生成树,而非树边我们便再也不用考虑了。之后我们要进行的便是找x到y的树上简单路径的边权最小值(我们不难想出这样求出的最小值一定是最优的)。对于求LCA我们使用倍增求解就可以,将par数组分成两个,一个记录祖先节点信息,另一个记录到达祖先节点的路径中的边权最小值。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const int LOG=15;
struct node {
      int a,b,c;
}d[110000];
int par[20][11000][3],dep[110000],fa[110000];
int cnt,to[210000],head[210000],nxt[210000],w[210000];
inline void read(int &x){
      int f=1;x=0;char s=getchar();
      while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
      while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
      x*=f;
}
inline bool cmp(const node &x,const node &y){return x.c>y.c;}
inline int sf(int x){return fa[x]==x?x:fa[x]=sf(fa[x]);}
inline void add(int u,int v,int val){
      nxt[++cnt]=head[u],to[cnt]=v,head[u]=cnt,w[cnt]=val;
      nxt[++cnt]=head[v],to[cnt]=u,head[v]=cnt,w[cnt]=val;
}
inline void dfs(int x,int pa){
      int i;
      for(i=head[x];i;i=nxt[i])
         if(to[i]!=pa){
            dep[to[i]]=dep[x]+1;dfs(to[i],x);
            par[0][to[i]][0]=x;par[0][to[i]][1]=w[i];
         }
}
inline int que(int x,int y){
      int ans=1000000007,i;
      if(dep[x]>dep[y])swap(x,y);
      for(i=LOG;i>=0;i--)
         if(dep[y]-dep[x]>=(1<<i)){
             ans=min(ans,par[i][y][1]);
             y=par[i][y][0];
         }
      if(x==y)return ans;
      for(i=LOG;i>=0;i--)
         if(par[i][x][0]!=par[i][y][0]){
             ans=min(ans,min(par[i][x][1],par[i][y][1]));
             x=par[i][x][0],y=par[i][y][0];
         }
      ans=min(ans,min(par[0][x][1],par[0][y][1]));
      return ans;
}
int main()
{     int n,m,i,j,k,x,y,sum=0,q;
      read(n),read(m);
      for(i=1;i<=m;i++)read(d[i].a),read(d[i].b),read(d[i].c);
      sort(d+1,d+m+1,cmp);
      for(i=1;i<=n;i++)fa[i]=i;
      for(i=1;i<=m;i++){
           if(sf(d[i].a)!=sf(d[i].b)){
               fa[sf(d[i].a)]=sf(d[i].b);
               add(d[i].a,d[i].b,d[i].c);
               sum++;
           }
      }
      for(i=1;i<=n;i++)
         if(!dep[i]){
             dep[i]=1;
             dfs(i,0);
         }
      for(i=0;i<LOG;i++)
         for(j=1;j<=n;j++){
            par[i+1][j][0]=par[i][par[i][j][0]][0];
            par[i+1][j][1]=min(par[i][j][1],par[i][par[i][j][0]][1]);
         }
      read(q);
      for(i=1;i<=q;i++){
           read(x),read(y);
           if(sf(x)!=sf(y)){puts("-1");continue;}
           printf("%d
",que(x,y));
      }
      return 0;
}

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const int LOG=15;
struct node {
      int a,b,c;
}d[110000];
int par[20][11000][3],dep[110000],fa[110000];
int cnt,to[210000],head[210000],nxt[210000],w[210000];
inline void read(int &x){
      int f=1;x=0;char s=getchar();
      while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
      while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
      x*=f;
}
inline bool cmp(const node &x,const node &y){return x.c>y.c;}
inline int sf(int x){return fa[x]==x?x:fa[x]=sf(fa[x]);}
inline void add(int u,int v,int val){
      nxt[++cnt]=head[u],to[cnt]=v,head[u]=cnt,w[cnt]=val;
      nxt[++cnt]=head[v],to[cnt]=u,head[v]=cnt,w[cnt]=val;
}
inline void dfs(int x,int pa){
      int i;
      for(i=head[x];i;i=nxt[i])
         if(to[i]!=pa){
            dep[to[i]]=dep[x]+1;dfs(to[i],x);
            par[0][to[i]][0]=x;par[0][to[i]][1]=w[i];
         }
}
inline int que(int x,int y){
      int ans=1000000007,i;
      if(dep[x]>dep[y])swap(x,y);
      for(i=LOG;i>=0;i--)
         if(dep[y]-dep[x]>=(1<<i)){
             ans=min(ans,par[i][y][1]);
             y=par[i][y][0];
         }
      if(x==y)return ans;
      for(i=LOG;i>=0;i--)
         if(par[i][x][0]!=par[i][y][0]){
             ans=min(ans,min(par[i][x][1],par[i][y][1]));
             x=par[i][x][0],y=par[i][y][0];
         }
      ans=min(ans,min(par[0][x][1],par[0][y][1]));
      return ans;
}
int main()
{     int n,m,i,j,k,x,y,sum=0,q;
      read(n),read(m);
      for(i=1;i<=m;i++)read(d[i].a),read(d[i].b),read(d[i].c);
      sort(d+1,d+m+1,cmp);
      for(i=1;i<=n;i++)fa[i]=i;
      for(i=1;i<=m;i++){
           if(sf(d[i].a)!=sf(d[i].b)){
               fa[sf(d[i].a)]=sf(d[i].b);
               add(d[i].a,d[i].b,d[i].c);
               sum++;
           }
      }
      for(i=1;i<=n;i++)
         if(!dep[i]){
             dep[i]=1;
             dfs(i,0);
         }
      for(i=0;i<LOG;i++)
         for(j=1;j<=n;j++){
            par[i+1][j][0]=par[i][par[i][j][0]][0];
            par[i+1][j][1]=min(par[i][j][1],par[i][par[i][j][0]][1]);
         }
      read(q);
      for(i=1;i<=q;i++){
           read(x),read(y);
           if(sf(x)!=sf(y)){puts("-1");continue;}
           printf("%d ",que(x,y));
      }
      return 0;
}

原文地址:https://www.cnblogs.com/yzxverygood/p/9124346.html