NOIP2013货车运输


题目描述

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。
数据范围:n最大10000,m最大50000,q为30000,z为100000.

输出

共有q行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。

样例输入

4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3

样例输出

3
-1
3

做法

两点之间尽可能大的最小承重路径一定在最大生成树上,于是问题转化为查询最大生成树上,两点之间的最小边的查询,可以倍增,也可以树剖。注意还有可能不能互相到达。

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
typedef long long ll;
const int N = 10010;
const int M = 50100;
const int inf = 0x3f3f3f3f;
inline int read() {char c=getchar(); int x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f;
}
using namespace std;
struct edge{int u,v,nxt,w;}E[M<<1],E0[M<<1];
int h[N],cc;
void add(int u,int v,int z) {E[cc].v=v;E[cc].w=z;E[cc].nxt=h[u];h[u]=cc;++cc;
}
bool cmp(edge a,edge b) {return a.w > b.w;}
int n,m;
int f[N][22],mn[N][22],fa[N];
int find(int x) {if(x==fa[x])return x;return fa[x]=find(fa[x]);
}
void merge(int x,int y) {x=find(x), y =find(y);if(x!=y) fa[x]=y;
}
void krus() {sort(E0+1,E0+1+m,cmp);rep(i,1,m) {int tx = find(E0[i].u), ty = find(E0[i].v);if(tx!=ty) {merge(tx,ty);add(E0[i].u,E0[i].v,E0[i].w);add(E0[i].v,E0[i].u,E0[i].w);}}
}
bool vis[N];
int dep[N];
void dfs(int u,int pre) {vis[u] = 1;f[u][0] = pre;for(int i=h[u];~i;i=E[i].nxt) {int v = E[i].v;if(!vis[v]&&v!=pre) {dep[v]=dep[u]+1;mn[v][0] = E[i].w;dfs(v,u);for(int j=1;j<=20;++j) f[v][j] = f[f[v][j-1]][j-1];for(int j=1;j<=20;++j) mn[v][j] = min(mn[v][j-1],mn[f[v][j-1]][j-1]);}}
}
void init() {memset(mn,inf,sizeof(mn));krus();rep(i,1,n)if(!vis[i])dfs(i,0);
//    rep(i,1,n) {
//        printf("%d :\n",i);
//        printf("dep[%d] = %d\n",i,dep[i]);
//        rep(j,0,3) printf("fa[%d][%d] = %d\n",i,j,f[i][j]);
//        rep(j,0,3) printf("mn[%d][%d] = %d\n",i,j,mn[i][j]);
//    }
}
int lca(int x,int y) {if(dep[x] > dep[y]) swap(x,y);int tx=x,ty=y;for(int d=dep[y]-dep[x],i=0;d;d>>=1,++i) if(d&1) ty = f[ty][i];if(tx == ty) return tx;for(int i=20;i>=0;--i) {if(f[tx][i]==f[ty][i]) continue;tx = f[tx][i], ty = f[ty][i];}return f[tx][0];
}
int ask_mn(int x,int p) {int ans = inf, tx=x;for(int d=dep[x]-dep[p],i=0;d;d>>=1,++i) if(d&1) {ans = min(ans,mn[tx][i]);tx = f[tx][i];}return ans;
}
int ask(int x,int y) {if(find(x)!=find(y)) return -1;int LCA = lca(x,y);return min(ask_mn(x,LCA),ask_mn(y,LCA));
}
int main() {n = read(), m =read();rep(i,1,n) h[i]=-1,fa[i]=i;rep(i,1,m) E0[i].u=read(),E0[i].v=read(),E0[i].w=read();init();int q = read();while(q--) {int x=read(), y =read();printf("%d\n",ask(x,y));}return 0;
}
//9 8
//1 2 4
//1 5 3
//2 3 3
//2 4 2
//3 9 2
//3 8 7
//5 7 6
//5 6 7

转载于:https://www.cnblogs.com/RRRR-wys/p/9384040.html

NOIP2013货车运输相关推荐

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

    学了一早上倍增,感觉lca还是tarjan好写. poj1330 1 #include <stdio.h> 2 #include <string.h> 3 #include & ...

  2. 倍增LCA NOIP2013 货车运输

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

  3. 【洛谷P1967】[NOIP2013]货车运输

    货车运输 题目链接 显然,从一点走到另一点的路径中,最小值最大的路径一定在它的最大生成树上 所以要先求出最大生成树,再在生成树上找最近公共祖先,同时求出最小值. 1 #include<iostr ...

  4. CodeVS3287[NOIP2013] 货车运输【Kruskal+倍增求LCA】

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

  5. NOIP2013 货车运输

    传送门 分析 贪心地想,对于两座城市之间,有多条道路,为了每次能多运输一些货物,一定会尽量往边权较大的路走,所以,一些边权较小的路是不会被走过,于是考虑 \(Kruskal\) 重构树,然后在新的图上 ...

  6. Luogu P1967 NOIP2013 货车运输

    这个题是很经典的生成树问题.第一次接触时对倍增算法的理解还不够透彻,没能打出来正解. 首先,原题中给出的是一幅图,询问从某点出发到另一点"需要经过的最短边的最大值".用floyd来 ...

  7. [NOIp2013] 货车运输

    比较水的一道题,之前做过类似的,今天没事儿干,写了这个...... 洛谷 P1967 传送门 算法很显然了,先求个生成树,在树上跑倍增...... 有两个地方被卡了,一个是并查集忘赋初值了,还有就是倍 ...

  8. [noip-2013] 货车运输

    https://www.luogu.org/problemnew/show/1967 /*这道题的基本思路在于求最大生成树,构建最大生成树的图然后问题相当于转化成求两点之间一条链上的最小值,因为这是已 ...

  9. 【杂题总汇】NOIP2013(洛谷P1967) 货车运输

    [洛谷P1967] 货车运输 重做NOIP提高组ing... +传送门-洛谷P1967+ ◇ 题目(copy from 洛谷) 题目描述 A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道 ...

最新文章

  1. C++编译器Qt Creator下载地址
  2. Android Studio -添加你见过的最牛Log*神器*
  3. aho-corasick php,GitHub - coralh/php-akm: Ahocorasick keyword match. Supports php7 and php5
  4. qtextbrowser 大量数据卡顿_800万行的数据,Excel 10秒钟就能完成统计?这个工具太良心了!...
  5. 基于框架的应用系统的质量属性
  6. 绝不能放进微波炉的10样东西,最后一个太意外
  7. 2021年9月24日和学生隆兴的学术讨论
  8. vba编程把纯文本转换成html,如何将一列文本与html标签转换为Excel中的vba格式文本...
  9. 编译安装时的--prefix参数的使用方法,很实用,mark一下
  10. 【MySQL】MySQL删除数据库的时候卡死
  11. win7关机快捷键_win7电脑键盘关机的操作方法
  12. 【IT】计算机基础知识
  13. linux的abrt目录满了,linux:abrt-cli list
  14. fcntl函数的作用及应用场景
  15. 杰理AC692X---691X,690X,692X芯片差异(2)
  16. 简洁免费的内网穿透工具
  17. 软件测试理论知识总结
  18. 2020年鼠年正月十二 淡然面对
  19. 人大金仓windows 10 安装闪退,改绿色安装方法,
  20. Visio 去交点处跨线

热门文章

  1. linux 用mutex定义一个linkedlist,一个高性能无锁非阻塞链表队列
  2. 35. 搜索插入位置011(二分查找)
  3. mysql采用 级触发_Mysql高级之触发器(trigger)
  4. [JavaWeb-XML]XML约束概述
  5. [Java基础]Stream流终结操作之forEachcount
  6. hdu 2069 Coin Change(改)-dp
  7. UDP(发短信:简单模拟)
  8. 添加库路经 linux,linux下的静态库与动态库
  9. 分支程序与循环程序设计-汇编实验二
  10. CF603D Ruminations on Ruminants(计算几何/Simson theorem)