洛谷1967货物运输(kruskal+lca倍增)
来源:互联网 发布:ip2780清零软件下载 编辑:程序博客网 时间:2024/05/07 07:05
题目描述
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 31 2 42 3 33 1 131 31 41 3
输出样例#1:3-13
说明
对于 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求最大生成树,发现加入一条边使x,y联通,则该条边的权值为所求。易证。
有一个巧妙的想法,因为边是由大到小加进来的,所以越往上的祖先所管的边权越小,因此我们只要跑一下最大生成树再跑lca便可求解。
<span style="font-size:18px;">#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <algorithm>#include <cmath>using namespace std;const int maxn=100005;struct data{ int u,v,w; bool operator <(const data&b)const{ return(w>b.w);}}e[maxn];int q,n,m,anc[maxn],fa[maxn],cnt=1,num,dep[maxn],f[maxn][19],val[maxn];inline int get(){ char c;while(!isdigit(c=getchar())); int p=c-48;while(isdigit(c=getchar()))p=p*10+c-48; return p;}inline int lca(int a,int b){ if(dep[a]<dep[b])swap(a,b); int j=0; while((1<<(j+1))<=dep[a])++j; for(int i=j;i>=0;--i){ //注意i可以取零 if((dep[a]-(1<<i))>=dep[b])a=f[a][i];}if(a==b)return a;for(int i=j;i>=0;--i){ if(f[a][i] && f[a][i]!=f[b][i]){ a=f[a][i]; b=f[b][i];}}return fa[a];}inline int Find(int x){ if(x==anc[x])return anc[x];else return (anc[x]=Find(anc[x])); }int main(){memset(f,0,sizeof(f));memset(fa,0,sizeof(fa)); n=get();m=get(); for(int i=1;i<=m;++i)e[i].u=get(),e[i].v=get(),e[i].w=get(); sort(e+1,e+1+m);num=n; for(int i=1;i<=n;++i)anc[i]=i; for(int i=1;i<=m;++i){ int x=Find(anc[e[i].u]); int y=Find(anc[e[i].v]); if(x!=y){ anc[x]=anc[y]=fa[x]=fa[y]=++n; //想象一下 fa[n]=0,val[n]=e[i].w,anc[n]=n; ++cnt;if(cnt==num)break;}}dep[n]=0;for(int i=n-1;i;--i){ dep[i]=dep[fa[i]]+1; f[i][0]=fa[i]; int j=1; while(f[f[i][j-1]][j-1])f[i][j]=f[f[i][j-1]][j-1],++j;}q=get();while(q--){ int x=get(),y=get(); if(Find(x)!=Find(y))printf("-1\n"); else printf("%d\n",val[lca(x,y)]);}return 0;}</span>
0 0
- 洛谷1967货物运输(kruskal+lca倍增)
- [洛谷 1967]货车运输---kruskal+lca(倍增)+遍历 or kruskal重构树+lca(倍增)
- 洛谷1967 火车运输 kruskal求最大生成树 倍增LCA维护最小值
- 洛谷 P1967 货车运输(Kruskal最大生成树&&倍增lca)
- BZOJ 3732 Network Kruskal+倍增LCA
- BZOJ 4144 Dijkstra+Kruskal+倍增LCA
- CodeVS1519 过路费【Kruskal+倍增求LCA】
- hdu5296(倍增lca)
- Codeforces587C(倍增LCA)
- bzoj1787(倍增lca)
- LCA模板(倍增)
- *树上倍增(LCA)
- 倍增算法(LCA)
- LCA(倍增)
- BZOJ 1977 Tree 次小生成树 (kruskal st表 倍增lca)
- NOIP2013 D1 T3 货车运输 树上倍增lca+Kruskal
- Luogu1967 [NOIP2013] 货车运输 解题报告【Kruskal】【LCA】【倍增】
- CodeVS3287[NOIP2013] 货车运输【Kruskal+倍增求LCA】
- 1.GitHub译文之安装Git
- DICOM:DICOM3.0标准中文版开源书籍之“git版本库合并”
- 《IOS_C语言》指针
- 结构体中经常碰到的一个错误 undeclared identifier
- uvalive4842(AC自动机+DP)
- 洛谷1967货物运输(kruskal+lca倍增)
- 详解Java中格式化输出浮点数
- 抽象类和接口的应用
- Git 服务器搭建与客户端安装
- Java-Java 7 增强后的switch分支语句
- Android实战简易教程-第四十八枪(App引导页面效果实现)
- Struts面试题
- 腾讯2015春招pc客户端开发练习卷
- noj 1004线性表的操作