好吧,遇上这种题,作为蒟蒻的我第一个想到的就是怎么打暴力,然而暴力都打不好QAQ!!!于是只能等教练讲解以后,然后在大犇的指导下终于做出来了。

对了,,好像还,没上题。。。。:

题目描述

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

输入输出格式

输入格式:

输入文件名为 truck.in。

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

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

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

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

输出格式:

输出文件名为 truck.out。

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

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

输入输出样例

输入样例#1:

4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
输出样例#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。

--------------------------------------------------------分割线--------------------------------------------------------

仔细思考一下,其实求最大载重量就是求出货车从某点到另一点的所有路径中最小权值最大的一条,于是可以用kruskal算法先处理出最大生成树,然后在树上进行倍增求lca,同时求出lca过程中经过的最小权值就行了。问题就在于如何在lca过程中求最小权值;很显然,直接在倍增过程中暴力求是行不通的,所以要预处理,在进行倍增预处理的同时记录下跳跃的该段中的最小权值,然后就可以很轻(ma)松(fan)的过了。如果还是有点不懂,请参考下列代码,其中有解释:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const int inf=0x7f7f7f7f;
const int maxn=(int)1e5+;
int n,m,tot,g[maxn],head[maxn],fa[maxn][],mm[maxn][];
//mm数组记录每次跳跃过程中跳跃段中的最小权值
int f[maxn],dep[maxn],minn=0x7fffffff;
bool vis[maxn];
struct Tree{
int to,val,next;
}road[maxn];
struct Edge{
int f,t,v;
}e[maxn];//邻接链表,不解释
inline int read()//读优,这个应该打得比较清楚
{
char ch=getchar();int num=;bool flag=false;
if(ch<''||ch>'')
if(ch=='-') flag=true,ch=getchar();
else ch=getchar();
while(ch>=''&&ch<='')
{num=num*+ch-'';
ch=getchar();}
return flag?-num:num;
}
void clear(int pd)//对数组进行预先处理
{
tot=;
if(pd)
{
memset(e,,sizeof(e));
memset(mm,0x7f,sizeof(mm));
}
memset(head,-,sizeof(head));
for(int i=;i<=n;i++)
f[i]=i;
}
bool cmp(Edge a,Edge b)
{return a.v>b.v;}
int find(int x)
{
if(f[x]!=x) f[x]=find(f[x]);
return f[x];
}
void add(int u,int v,int w)
{
road[++tot].to=v;
road[tot].val=w;
road[tot].next=head[u];
head[u]=tot;
}
void build()//kruskal算法,如果不会,出门左转自行百度
{
int a,b;
sort(e+,e+m+,cmp);
for(int i=;i<=m;i++)
{
a=find(e[i].f);
b=find(e[i].t);
if(a!=b)
{
add(e[i].f,e[i].t,e[i].v);
add(e[i].t,e[i].f,e[i].v);
f[a]=b;
}
if(tot==m*-)break;
}
}
void dfs(int x)
//深搜进行预处理,当然,预处理还有另外一种用两个变量的写法,我就不写了,可以到网上去看看
//据说那种写法比这种要好一点,
{
for(int i=;i<=;i++)
{
if(mm[x][i-]<inf)
mm[x][i]=min(mm[x][i-],mm[fa[x][i-]][i-]);
    /*这个应该不难理解,每次跳的时候都要更新最小值,切记,要在向上跳之前记录*/
fa[x][i]=fa[fa[x][i-]][i-];
}
vis[x]=;
for(int i=head[x];i!=-;i=road[i].next)
{
int y=road[i].to;
if(y!=fa[x][])
{
dep[y]=dep[x]+;
mm[y][]=road[i].val;
      /*这里解释下,某一点跳一步的最小权值就是这两点间的权值*/
fa[y][]=x;
dfs(y);
}
}
}
int lca(int u,int v)//倍增求lca,不解释
{
if(dep[u]<dep[v]) swap(u,v);
int d=dep[u]-dep[v];
for(int i=;i<=;i++)
if(d&(<<i))
{
minn=min(minn,mm[u][i]);
u=fa[u][i];
}
if(u==v) return minn;
for(int i=;i>=;i--)
{
if(fa[u][i]!=fa[v][i])
{
minn=min(minn,min(mm[u][i],mm[v][i]));
u=fa[u][i];
v=fa[v][i];
}
}
minn=min(minn,min(mm[u][],mm[v][]));
return minn;
}
int main()
{
int x,y,q;
scanf("%d%d",&n,&m);
clear();
for(int i=;i<=m;i++)
{
e[i].f=read();
e[i].t=read();
e[i].v=read();
}
scanf("%d",&q);
build();//最大生成树
memset(vis,false,sizeof(vis));
for(int i=;i<=n;i++)
if(!vis[i]) dfs(i);//进行lca倍增预处理
for(int i=;i<=q;i++)
{
scanf("%d%d",&x,&y);
minn=inf;
if(find(x)!=find(y))
{printf("-1\n");continue;}
printf("%d\n",lca(x,y));
}
return ;
}

-----------------------------------------------------------------分割线-----------------------------------------------------------------------

作为第三题,果然还是有点难度的,神犇的路还很漫长,加油吧!

NOIP2013 D1 T3 货车运输的更多相关文章

  1. NOIP2013 DAY2 T3火车运输

    传送门 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况 ...

  2. [NOIP2013][LGOJ P1967]货车运输

    Problem Link 题目描述 A国有n座城市,编号从1到n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重 ...

  3. [NOIP2013提高组]货车运输

    题目:洛谷P1967.Vijos P1843.codevs3287. 题目大意:有n个城市m条道路,每条道路有一个限重,规定货车运货不能超过限重.有一些询问,问你两个城市之间一次最多能运多少重的货(可 ...

  4. 【NOIP2013/Codevs3287】货车运输-最小生成树(大)-树上倍增

    https://www.luogu.org/problemnew/show/P1967 由题可知,我们走的路的边应尽可能大,所以通过kruscal建最大生成树的图,再树上倍增,注意可能有多棵树; #i ...

  5. [NOIP2013 提高组] 货车运输

    前言 使用算法:堆优化 \(prim\) , \(LCA\) . 题意 共有 \(n\) 个点,有 \(m\) 条边来连接这些点,每条边有权值.有 \(q\) 条类似于 \(u\) \(v\) 询问, ...

  6. NOIP2013 货车运输(最大生成树,倍增)

    NOIP2013 货车运输(最大生成树,倍增) A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道 ...

  7. [Luogu 1967] NOIP2013 货车运输

    [Luogu 1967] NOIP2013 货车运输 一年多前令我十分头大的老题终于可以随手切掉了- 然而我这码风又变毒瘤了,我也很绝望. 看着一年前不带类不加空格不空行的清纯码风啊,时光也好像回去了 ...

  8. xsy 2018 【NOIP2013】货车运输

    [NOIP2013]货车运输 Description A 国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有q辆货车在运输货物,司机们想知道每辆车在不超 ...

  9. NOIP2013 货车运输 (最大生成树+树上倍增LCA)

    死磕一道题,中间发现倍增还是掌握的不熟 ,而且深刻理解:SB错误毁一生,憋了近2个小时才调对,不过还好一遍AC省了更多的事,不然我一定会疯掉的... 3287 货车运输 2013年NOIP全国联赛提高 ...

随机推荐

  1. 解决tomcat占用8080端口问题图文详解

    相信很多朋友都遇到过这样的问题吧,tomcat死机了,重启eclipse之后,发现 Several ports (8080, 8009) required by Tomcat v6.0 Server ...

  2. NOIP模拟赛13

    期望得分:100+0+100=200 实际得分:100+5+100=205 T1 空间卡到30M.. n<=2.5*1e7 若x是整除区间[1,n]每个数的最小的数,那么对[1,n]每个数分解质 ...

  3. 计算方法 -- 解线性方程组直接法(LU分解、列主元高斯消元、追赶法)

    #include <iostream> #include <cstdio> #include <algorithm> #include <cstdlib> ...

  4. MongoDB 分页

    使用Skip和limit可以如下做数据分页: Code: page1 = db.things.find().limit(20) page2 = db.things.find().skip(20).li ...

  5. Intellij IDEA 快捷键整理(转)

    Ctrl+Shift + Enter,语句完成 “!”,否定完成,输入表达式时按 “!”键 Ctrl+E,最近的文件 Ctrl+Shift+E,最近更改的文件 Shift+Click,可以关闭文件 C ...

  6. GridControl详解(七)事件

    private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventA ...

  7. sqoop一些语法的使用

    参数详细资料 观看这个博客 http://shiyanjun.cn/archives/624.html Sqoop可以在HDFS/Hive和关系型数据库之间进行数据的导入导出,其中主要使用了impor ...

  8. css3同心圆闪烁扩散效果

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  9. 爬虫实战--使用Selenium模拟浏览器抓取淘宝商品美食信息

    from selenium import webdriver from selenium.webdriver.common.by import By from selenium.common.exce ...

  10. c语言学习笔记.预处理.#ifndef

    #ifndef -> if not define 配合 #endif使用 在h头文件中使用,防止重复包含和编译. 也可以用条件编译来实现. 例如: 编写头文件 test.h 在头文件开头写上两行 ...