刷题总结——货车运输

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了刷题总结——货车运输相关的知识,希望对你有一定的参考价值。

题目:

题目背景

NOIP2013 提高组 Day1 试题。

题目描述

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。 

样例数据 1

输入  [复制]

 

 

4 3 
1 2 4 
2 3 3 
3 1 1 

1 3 
1 4 
1 3

输出


-1 
3

备注

【数据范围】
对于 30% 的数据,0<n<1,000 ;0<m<10,000 ;0<q<1,000; 
对于 60% 的数据,0<n<1,000 ;0<m<50,000 ;0<q<1,000; 
对于 100% 的数据,0<n<10,000 ;0<m<50,000 ;0<q<30,000 ;0≤z≤100,000。 

题解:

最大生成树然后在树上倍增就可以了···md并查集竟然打挂卡了我半天···

突然发现倍增法那么有用····

代码:

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=1e5+5;
const int M=5e5+5;
int R()
{
  int f=0;
  char c;
  for(c=getchar();c<0||c>9;c=getchar());
  for(;c>=0&&c<=9;c=getchar())
    f=(f<<3)+(f<<1)+c-0;
  return f;
}
int n,m,first[N],go[M],val[M],next[M],q,tot=0,g[N][35],deep[N],minn[N][35],father[N];
bool visit[N];
struct node
{
  int from;
  int go;
  int w;
}edge[M]; 
inline int getfa(int a)
{
  if(father[a]==a)  return a;
  else
  {  
    father[a]=getfa(father[a]);
    return father[a];
  }
}
bool cmp(node a,node b)
{
  return a.w>b.w;
}
void comb(int a,int b,int c)
{
  next[++tot]=first[a],first[a]=tot,go[tot]=b,val[tot]=c;
  next[++tot]=first[b],first[b]=tot,go[tot]=a,val[tot]=c;
}
inline void dfs(int now,int fa)
{
  visit[now]=true;
  for(int e=first[now];e;e=next[e])
  {
    int v=go[e];
    if(v==fa||visit[v]==true)  continue;
    g[v][0]=now;
    minn[v][0]=max(val[e],minn[v][0]);
    deep[v]=deep[now]+1;
    dfs(v,now);
  }
}
inline int getans(int x,int y)
{
  int minx=1e+9,miny=1e+9,i,j;
  if(deep[x]<deep[y])  swap(x,y);
  for(i=0;(1<<i)<=deep[x];i++);
  i--;
  for(j=i;j>=0;j--)
  {
    if(deep[x]-(1<<j)>=deep[y])
    {
      minx=min(minx,minn[x][j]);
      x=g[x][j];
    }
  }
  if(x==y)  return minx;
  for(i=32;i>=0;i--)
  {
    if(g[x][i]!=g[y][i])
    {
      minx=min(minx,minn[x][i]);
      miny=min(miny,minn[y][i]);
      x=g[x][i];
      y=g[y][i];
    }
  }
  minx=min(minx,minn[x][0]);
  miny=min(miny,minn[y][0]);
  return min(minx,miny);
}
int main()
{
  //freopen("a.in","r",stdin);
  n=R(),m=R();
  for(int i=1;i<=n;i++)
    father[i]=i;
  int x,y,z;
  for(int i=1;i<=m;i++)
  {
    x=R(),y=R(),z=R();
    edge[i].from=x;
    edge[i].go=y;
    edge[i].w=z;
  }
  sort(edge+1,edge+m+1,cmp);
  for(int i=1;i<=m;i++)
  {
    if(getfa(edge[i].from)!=getfa(edge[i].go))        
    {
      father[getfa(edge[i].from)]=getfa(edge[i].go);
      comb(edge[i].from,edge[i].go,edge[i].w);
    }
  }
  for(int i=1;i<=n;i++)
  {
    if(!visit[i])
    {  
      dfs(i,0);
      minn[i][0]=1e+9;
      g[i][0]=i;
    }
  }
  for(int i=1;i<=32;i++)
    for(int j=1;j<=n;j++)
    {  
      g[j][i]=g[g[j][i-1]][i-1];
      minn[j][i]=min(minn[g[j][i-1]][i-1],minn[j][i-1]);
    }
  q=R();
  while(q--)
  {
    x=R(),y=R();
    if(getfa(x)!=getfa(y))  cout<<"-1"<<endl;    
    else
      cout<<getans(x,y)<<endl;
  }
  return 0;
}

 
















以上是关于刷题总结——货车运输的主要内容,如果未能解决你的问题,请参考以下文章

3287 货车运输

货车运输

华为OD机试 -快递运输(Java) | 机试题+算法思路+考点+代码解析 2023

货车运输

Codevs 3287 货车运输

[Codevs] 3287 货车运输