倍增LCA NOIP2013 货车运输

货车运输

题目描述

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。

NOIP2013,kidding me?

出个模板题???

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 int n,m,q;
  7 struct data{
  8     int s,e,d;
  9 }edge[50010];
 10 int f[10010];
 11 struct dt{
 12     int next,to,dis;
 13 }eg[20010];
 14 int cnt;
 15 int head[10010],deep[10010],fa[10010][32],w[10010][32];
 16 bool cmp(const data&a,const data&b){
 17     return a.d>b.d;//!
 18 }
 19 int find(int x){
 20     if(x!=f[x]) return f[x]=find(f[x]);//!
 21     return f[x];//!
 22 }
 23 void add(int start,int end,int dd){
 24     eg[++cnt].next=head[start];
 25     eg[cnt].to=end;
 26     eg[cnt].dis=dd;
 27     head[start]=cnt;
 28 }
 29 void build(){
 30     int ct=0;
 31     for(int i=1;i<=m;i++){
 32         int f1=find(edge[i].s);
 33         int f2=find(edge[i].e);
 34         if(f1!=f2){
 35             f[f1]=f2;
 36             add(edge[i].s,edge[i].e,edge[i].d);
 37             add(edge[i].e,edge[i].s,edge[i].d);
 38             ct++;
 39         }
 40         if(ct==n-1) break;
 41     }
 42 }
 43 void dfs(int u){
 44     for(int i=head[u];i;i=eg[i].next)
 45         if(!deep[eg[i].to]){
 46             deep[eg[i].to]=deep[u]+1;
 47             fa[eg[i].to][0]=u;
 48             w[eg[i].to][0]=eg[i].dis;
 49             dfs(eg[i].to);
 50         }
 51 }
 52 void work(){
 53     for(int j=1;(1<<j)<=n;j++)
 54         for(int i=1;i<=n;i++)
 55             if(fa[i][j-1]!=-1){
 56                 fa[i][j]=fa[fa[i][j-1]][j-1];
 57                 w[i][j]=min(w[i][j-1],w[fa[i][j-1]][j-1]);
 58             }
 59 }
 60 int lca(int x,int y){
 61     int rt=0x3f3f3f3f;
 62     if(deep[x]<deep[y]) swap(x,y);
 63     int i=0;
 64     for(i=0;(1<<i)<=deep[x];i++);
 65     i--;
 66     for(int j=i;j>=0;j--)
 67         if(deep[x]-(1<<j)>=deep[y]){
 68             rt=min(rt,w[x][j]);
 69             x=fa[x][j];
 70         }
 71     if(x==y) return rt;//!
 72     for(int j=i;j>=0;j--)
 73         if(fa[x][j]!=-1&&fa[x][j]!=fa[y][j]){
 74             rt=min(rt,min(w[x][j],w[y][j]));
 75             x=fa[x][j];
 76             y=fa[y][j];
 77         }
 78     return min(rt,min(w[x][0],w[y][0]));
 79 }
 80 int main(){
 81     scanf("%d%d",&n,&m);
 82     for(int i=1;i<=m;i++) scanf("%d%d%d",&edge[i].s,&edge[i].e,&edge[i].d);
 83     sort(edge+1,edge+m+1,cmp);
 84     for(int i=1;i<=n;i++) f[i]=i;
 85     build();
 86     memset(fa,-1,sizeof(fa));
 87     deep[1]=1;
 88     dfs(1);
 89     work();
 90     scanf("%d",&q);
 91     int ss=0,ee=0;
 92     for(int i=1;i<=q;i++){
 93         scanf("%d%d",&ss,&ee);
 94         if(find(ss)!=find(ee)){
 95             printf("-1\n");
 96             continue;
 97         }
 98         printf("%d\n",lca(ss,ee));
 99     }
100     return 0;
101 }
时间: 2024-10-10 15:06:42

倍增LCA NOIP2013 货车运输的相关文章

poj1330|bzoj3732|noip2013 货车运输 kruskal+倍增lca

学了一早上倍增,感觉lca还是tarjan好写. poj1330 1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 #include <algorithm> 5 #define DEG 20//2^20 6 #define maxn 10010 7 using namespace std; 8 struct node 9 { 10 int v, next; 11 }a[maxn*2

【NOIP2013货车运输】

描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 格式 输入格式 第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路. 接下来 m 行每行 3 个整数 x.y.z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路.注意:x 不等于 y,两座城市之间可能有多条道路. 接

Codevs3278[NOIP2013]货车运输

3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入描述 Input Description 第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和

noip2013货车运输

P1967 货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入输出格式 输入格式: 输入文件名为 truck.in. 输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道 路. 接下来 m 行每行 3 个整数 x. y. z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y

NOIP2013 货车运输(最大生成树+LCA)

模拟考试的时候暴搜,结果写丑了,分都不分 下来啃了一下题解,发现要用到一个叫做倍增的东西,还没有学过.但是老师说的,没有那个东西,写暴力也有30~40分... 我觉得最大生成树还是很好理解的,因为我们要求的是图中任意两个点之间的路径上,使得边权的最小值尽量大.因此首先求最大生成树. 当我们得到最大生成树后,要求两个点之间边权最小值,我们可以首先找到他们的公共祖先.这里有一篇写得很详细的代码,并且注明了各种写法的得分http://blog.csdn.net/gengmingrui/article/

洛谷 1967 NOIP2013 货车运输

这个题目在看题解的情况下,写了6小时左右.感觉贼心累啊.读入错误,运行顺序错误,一大堆错误.现在很为自己写长代码担心... 毕竟花了这么长时间,在考场那种高压的情况下.还不知道发挥如何~ 题目说起来很Easy:1.读入2.求最大生成树3.求倍增求LCA 并记录 路径上的 最小值4.输出 放出我的丑不拉几的代码~ 1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4   5 int Min[20

[NOIP2013]货车运输

[题目描述] 思路{直接最大生成树+树链剖分即可.} 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #include<vector> 8 #include<set> 9 #include<map> 10 #d

【BZOJ3732】Network,NOIP2013货车运输,ygylca

跟NOIP的题是一模一样的,我重写了一遍,这个代码更清晰一点. 思路见http://blog.csdn.net/vmurder/article/details/38734663 但我仍要再说一遍思路. 首先我们最小生成树建图,这个就不进行证明了,因为按照kruskal建图的话,每遍历过一条边,就相当于有一些询问间有了道路,而且一定是该边. 然后就是ygylca了.思想:把要处理的东西扔到该节点,按一定顺序在该节点处理,并且处理后扔到lca,然后因为到了lca处时有些需要顺序处理的信息已经处理完了

【bzoj4242】水壶 BFS+最小生成树+倍增LCA

题目描述 JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有P个,编号为1...P. JOI君只能进入建筑物与原野,而且每次只能走到相邻的区域中,且不能移动到市外. JOI君因为各种各样的事情,必须在各个建筑物之间往返.虽然建筑物中的冷气设备非常好,但原野上的日光十分强烈,因此在原野上每走过一个区域都需要1单位的水.此外,原野上没有诸如自动售货机.饮水处之类的东西,因此IOI市的市民一般都携带水壶出