洛谷P1967 [NOIP2013提高组Day1T2]货车运输

P1967 货车运输

题目描述

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。

【题解】

最大生成树+树上倍增,证明可用反证法或者显然法(唔)

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 #define min(a, b) ((a) < (b) ? (a) : (b))
  7
  8 inline void read(int &x)
  9 {
 10     x = 0;char ch = getchar(), c = ch;
 11     while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar();
 12     while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar();
 13     if(c == ‘-‘) x = -x;
 14 }
 15
 16 inline void swap(int &a, int &b)
 17 {
 18     int tmp = a;a = b;b = tmp;
 19 }
 20
 21 const int MAXN = 10000 + 10;
 22 const int MAXM = 50000 + 10;
 23 const int INF = 0x3f3f3f3f;
 24
 25 int n,m,u[MAXM],v[MAXM],w[MAXM],cnt[MAXM],q,s,t,fa[MAXN],b[MAXM];
 26
 27 bool cmp(int a, int b)
 28 {
 29     return w[a] > w[b];
 30 }
 31
 32 struct Edge
 33 {
 34     int u,v,w,next;
 35     Edge(int _u, int _v, int _w, int _next){u = _u, v = _v, w = _w, next = _next;}
 36     Edge(){}
 37 }edge[MAXN << 1];
 38 int head[MAXN], cntt;
 39 inline void insert(int a, int b, int c)
 40 {
 41     edge[++cntt] = Edge(a,b,c,head[a]);
 42     head[a] = cntt;
 43 }
 44
 45 int deep[MAXN], p[20][MAXN], mi[20][MAXN];
 46
 47 void dfs(int u)
 48 {
 49     b[u] = 1;
 50     for(register int pos = head[u];pos;pos = edge[pos].next)
 51     {
 52         int v = edge[pos].v;
 53         if(b[v])continue;
 54         deep[v] = deep[u] + 1;
 55         p[0][v] = u;
 56         mi[0][v] = edge[pos].w;
 57         dfs(v);
 58     }
 59 }
 60
 61 void yuchuli()
 62 {
 63     int M = 0;
 64     while((1 << M) <= n) ++ M;
 65     -- M;
 66     for(register int i = 1;i <= M;++ i)
 67         for(register int j = 1;j <= n;++ j)
 68             p[i][j] = p[i - 1][p[i - 1][j]];
 69     for(register int i = 1;i <= M;++ i)
 70         for(register int j = 1;j <= n;++ j)
 71             mi[i][j] = min(mi[i - 1][p[i - 1][j]], mi[i - 1][j]);
 72 }
 73
 74 int LCA(int va, int vb)
 75 {
 76     if(deep[va] < deep[vb]) swap(va, vb);
 77     int M = 0;
 78     while((1 << M) <= n)++ M;
 79     -- M;
 80     for(register int i = M;i >= 0;-- i)
 81         if(deep[vb] + (1 << i) <= deep[va])
 82             va = p[i][va];
 83     if(va == vb)return va;
 84     M = 0;
 85     while((1 << M) <= deep[va]) ++ M;
 86     -- M;
 87     for(register int i = M;i >= 0;-- i)
 88         if(p[i][va] != p[i][vb])
 89         {
 90             va = p[i][va];
 91             vb = p[i][vb];
 92         }
 93     return p[0][va];
 94 }
 95
 96 int find(int x)
 97 {
 98     return x == fa[x] ? x : fa[x] = find(fa[x]);
 99 }
100
101 int main()
102 {
103     read(n), read(m);
104     for(register int i = 1;i <= m;++i)
105         read(u[i]), read(v[i]), read(w[i]), cnt[i] = i;
106     for(register int i = 1;i <= n;++ i)
107         fa[i] = i;
108     std::sort(cnt + 1, cnt + 1 + m, cmp);
109     for(register int i = 1;i <= m;++i)
110     {
111         int f1 = find(u[cnt[i]]), f2 = find(v[cnt[i]]);
112         if(f1 != f2)
113         {
114             fa[f1] = f2;
115             insert(u[cnt[i]], v[cnt[i]], w[cnt[i]]);
116             insert(v[cnt[i]], u[cnt[i]], w[cnt[i]]);
117         }
118     }
119     for(register int i = 1;i <= n;++ i)
120     {
121         if(!b[i])
122         {
123             deep[i] = 1;
124             dfs(i);
125         }
126     }
127     yuchuli();
128     read(q);
129     int s,t;
130     int M = 0;
131     while((1 << M) <= n) ++ M;
132     -- M;
133     for(register int i = 1;i <= q;++ i)
134     {
135         read(s), read(t);
136         int f1 = find(s), f2 = find(t);
137         if(f1 != f2)
138         {
139             printf("-1\n");
140             continue;
141         }
142         int lca = LCA(s, t);
143         int mi1 = INF, mi2 = INF;
144         for(register int j = M;j >= 0;-- j)
145             if(p[j][s] && deep[p[j][s]] >= deep[lca])
146             {
147                 mi1 = min(mi1, mi[j][s]);
148                 s = p[j][s];
149             }
150         for(register int j = M;j >= 0;-- j)
151             if(p[j][t] && deep[p[j][t]] >= deep[lca])
152             {
153                 mi2 = min(mi2, mi[j][t]);
154                 t = p[j][t];
155             }
156         printf("%d\n", min(mi1, mi2));
157     }
158     return 0;
159 }

NOIP2013Day1T3

时间: 2025-01-31 06:41:09

洛谷P1967 [NOIP2013提高组Day1T2]货车运输的相关文章

洛谷P1311 [NOIP2011提高组Day1T2] 选择客栈

P1311 选择客栈 题目描述 丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号.每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费. 两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中.晚上,他们打算选择一家咖啡店喝咖啡,要求咖啡店位于两人住的两家客栈之间(包括他们住的客栈),且咖啡店的最低消费不超过 p . 他们想知道总共有多少种选择

洛谷P1970 [NOIP2013提高组Day2T2] 花匠

P1970 花匠 题目描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定 把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希 望剩下的花排列得比较别致. 具体而言,栋栋的花的高度可以看成一列整数h1,h2..hn.设当一部分花被移走后,剩下的花的高度依次为g1,g2..gn,则栋栋希望下面两个条件中至少有一个满足: 条件 A:对于所有g(2i)>g(2i-1),g(2i)>g(2i+1) 条件 B:对于所有g(2i)<g(2i

洛谷P1969 [NOIP2013提高组Day2T1] 积木大赛

P1969 积木大赛 题目描述 春春幼儿园举办了一年一度的“积木大赛”.今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi. 在搭建开始之前,没有任何积木(可以看成n块高度为 0 的积木).接下来每次操作,小朋友们可以选择一段连续区间[l, r],然后将第第 L 块到第 R 块之间(含第 L 块和第 R 块)所有积木的高度分别增加1. 小 M 是个聪明的小朋友,她很快想出了建造大厦的最佳策略,使得建造所需的操作次数最少.但她不是一个勤于动

【NOIP2013提高组】货车运输

https://www.luogu.org/problem/show?pid=1967 思考一下,将图的所有边按边权从大到小依次加入图,则当u与v第一次连通时,刚加入的边就是使u与v两点的路径中的最小边最大的边. 将图的所有边按边权从大到小依次加入图?这不就是Kruscal算法最大生成树吗! 所以我们只需要对原图求最大生成树,对于每个询问求两点的路径上的最小边就可以了.虽然可以用树剖+ST表优化,但是暴力求LCA+暴力爬链也能过了. 暴力LCA+暴力爬链: #include <algorithm

洛谷P1312 [NOIOP2011提高组 Day1T3]Mayan游戏

Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定的步数内消除所有的方块,消除方块的规则如下: 1 .每步移动可以且仅可以沿横向(即向左或向右)拖动某一方块一格:当拖动这一方块时,如果拖动后到达的位置(以下称目标位置)也有方块,那么这两个方块将 交换位置(参见输入输出样例说明中的图6 到图7 ):如果目标位置上没有方块,那么被拖动的

洛谷P1080 [NOIP2012提高组D1T2]国王游戏 [2017年5月计划 清北学堂51精英班Day1]

P1080 国王游戏 题目描述 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右 手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排 成一排,国王站在队伍的最前面.排好队后,所有的大臣都会获得国王奖赏的若干金币,每 位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右 手上的数,然后向下取整得到的结果. 国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序, 使得获得奖赏最多的大

洛谷P1003 [NOIP2011提高组Day1T1]铺地毯

P1003 铺地毯 题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到n .现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上. 地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号.注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖. 输入输出格式 输入格式: 输入文件名为carpet.in . 输入共n+2 行. 第一行,一个整数n

【模板】LIS模板 洛谷P1091 [NOIP2004提高组]合唱队形 [2017年4月计划 动态规划11]

以题写模板. 写了两个:n^2版本与nlogn版本 P1091 合唱队形 题目描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足T1<...<Ti>Ti+1>…>TK(1<=i<=K). 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形. 输入输出格

二分查找or线段树(借教室洛谷1083vijos1782NOIP 2012 提高组 第二天 第二题)

在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自然希望编程解决这个问题.我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借.共有m份订单,每份订单用三个正整数描述,分别为dj,sj,tj,表示某租借者需要从第sj天到第tj天租借教室(包括第sj天和第tj天),每天需要租借dj个教室. 我们假定,租借者对教室的大小.地点没有要求.即对于每份