NOIP2013 D1 T3 货车运输
好吧,遇上这种题,作为蒟蒻的我第一个想到的就是怎么打暴力,然而暴力都打不好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。
输入输出样例
- 4 3
- 1 2 4
- 2 3 3
- 3 1 1
- 3
- 1 3
- 1 4
- 1 3
- 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 货车运输的更多相关文章
- NOIP2013 DAY2 T3火车运输
传送门 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况 ...
- [NOIP2013][LGOJ P1967]货车运输
Problem Link 题目描述 A国有n座城市,编号从1到n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重 ...
- [NOIP2013提高组]货车运输
题目:洛谷P1967.Vijos P1843.codevs3287. 题目大意:有n个城市m条道路,每条道路有一个限重,规定货车运货不能超过限重.有一些询问,问你两个城市之间一次最多能运多少重的货(可 ...
- 【NOIP2013/Codevs3287】货车运输-最小生成树(大)-树上倍增
https://www.luogu.org/problemnew/show/P1967 由题可知,我们走的路的边应尽可能大,所以通过kruscal建最大生成树的图,再树上倍增,注意可能有多棵树; #i ...
- [NOIP2013 提高组] 货车运输
前言 使用算法:堆优化 \(prim\) , \(LCA\) . 题意 共有 \(n\) 个点,有 \(m\) 条边来连接这些点,每条边有权值.有 \(q\) 条类似于 \(u\) \(v\) 询问, ...
- NOIP2013 货车运输(最大生成树,倍增)
NOIP2013 货车运输(最大生成树,倍增) A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道 ...
- [Luogu 1967] NOIP2013 货车运输
[Luogu 1967] NOIP2013 货车运输 一年多前令我十分头大的老题终于可以随手切掉了- 然而我这码风又变毒瘤了,我也很绝望. 看着一年前不带类不加空格不空行的清纯码风啊,时光也好像回去了 ...
- xsy 2018 【NOIP2013】货车运输
[NOIP2013]货车运输 Description A 国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有q辆货车在运输货物,司机们想知道每辆车在不超 ...
- NOIP2013 货车运输 (最大生成树+树上倍增LCA)
死磕一道题,中间发现倍增还是掌握的不熟 ,而且深刻理解:SB错误毁一生,憋了近2个小时才调对,不过还好一遍AC省了更多的事,不然我一定会疯掉的... 3287 货车运输 2013年NOIP全国联赛提高 ...
随机推荐
- ASP.NET Core的身份认证框架IdentityServer4--(5)自定义用户登录(通过接口登录,无UI版本)
官网接口详解文档地址:文档地址 (PS:可通过接口名称搜索相应接口信息.) 源码地址:https://github.com/YANGKANG01/IdentityServer4-IdentityAut ...
- .net core 中 identity server 4 之术语
id4的职责: 保护你的资源 通过本地 账户库(Account Store)或者外部身份提供其 认证用户 提供Session管理以及SSO 管理和认证客户端 发行身份及访问Token给客户端 验证To ...
- logstash 收集 IIS 日志实践
IIS日志示例: 2017-02-20 00:55:40 127.0.0.1 GET /MkWebAPI/swagger/ui/index - 80 - 127.0.0.1 Mozilla/5.0+( ...
- 更改gradle的java的class文件输出目录的结构
group 'com.thinkvenus.common'version '1.0-SNAPSHOT' apply plugin: 'java' sourceCompatibility = 1.8 r ...
- 持续集成工具Jenkins安装、部署、使用
本文介绍jenkins,利用其做项目发布与持续集成交付工具. 一.Jenkins是什么? Jenkins是基于Java开发的一种持续集成工具,用于监控持续重复的工作,功能包括: 1.持续的软件版本发布 ...
- php常用表单验证类用法实例
<?php /** * 页面作用:常用表单验证类 * 作 者:欣然随风 * QQ:276624915 */ class class_post { //验证是否为指定长度的字母/数字组合 func ...
- OSCP考试回顾
技术背景 从2011年开始接触学习渗透测试,全职做过的职位有渗透测试,Python后端研发,DevOps,甲方安全打杂. 学习过程 首先考试报名,交钱.买了价值800美元的一个月lab,包含Pente ...
- makefile初步制作,arm-linux- (gcc/ld/objcopy/objdump)详解【转】
转自:http://www.cnblogs.com/lifexy/p/7065175.html 在linux中输入vi Makefile 来实现创建Makefile文件 注意:命令行前必须加TAB键 ...
- 老版本ubuntu更新源地址以及sources.list的配置方法 转
转自(http://blog.csdn.net/snaking616/article/details/52966634) 1.国内可用的更新源地址: (1)中科大地址 http://mirrors.u ...
- Appium环境搭建说明(包括报错处理)
Appium环境搭建说明 一.环境配置 前提是windows系统已安装以下软件: 1.jdk 我装的是1.8.0 2.android-sdk 3.python,3.4-3.6 5.Node.js,v8 ...