【NOIP】提高组2013 货车运输
【算法】最大生成树+LCA(倍增)
【题解】两点间选择一条路径最小值最大的路径,这条路径一定在最大生成树上,因为最大生成树就是从边权最大的边开始加的。
先求原图的最大生成树(森林),重新构图,然后用一个超级根连向每棵树的根。
对于每个询问,在树上跑z=LCA(x,y),答案就是x到z,z到y路上的最小值。
这个最小值可以在LCA(倍增)的过程中顺便维护(ms数组),和祖先(倍增)数组的维护方式类似。
ms[e[x].to][0]=e[i].w;
ms[x][i]=min(ms[x][i-1],ms[f[x][i-1]][i-1]);
求ans的时候,x,y每次向上推进都求一次ans=min(ans,...),具体可以看程序。
【注意】(只是提醒自己T_T)
1.每次要更新x,y的位置前先求ans。
2.无向边建两条,数组要开大,而且后面求生成树的时候要用建边总数而不是原边总数m!!!
3.超级根用0容易出错,用比maxn大的数字即可。
4.重新构图的新边表和旧边表各种变量注意区分
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f,maxn=;
bool ok[maxn];
struct cyc{int next,from,to,w;}eo[],e[];
int cnt,tot,head[maxn],heads[maxn],fa[maxn],f[maxn][],ms[maxn][],vis[maxn],deep[maxn],n,m,q;
void insert(int u,int v,int w)
{cnt++;eo[cnt].from=u;eo[cnt].to=v;eo[cnt].w=w;eo[cnt].next=heads[u];heads[u]=cnt;}
void ins(int u,int v,int w)
{tot++;e[tot].from=u;e[tot].to=v;e[tot].w=w;e[tot].next=head[u];head[u]=tot;}
int getfa(int x)
{return fa[x]==x?x:(fa[x]=getfa(fa[x]));}
bool cmp(cyc a,cyc b)
{return a.w>b.w;}
void dfs(int x)
{
vis[x]=;
for(int i=;(<<i)<=deep[x];i++)
f[x][i]=f[f[x][i-]][i-],
ms[x][i]=min(ms[x][i-],ms[f[x][i-]][i-]);
// printf("head[%d]=%d",x,head[x]);
for(int i=head[x];i;i=e[i].next){//printf("i=%d\n",i);
if(!vis[e[i].to])
{
int now=e[i].to;
deep[now]=deep[x]+;
f[now][]=x;
ms[now][]=e[i].w;
dfs(now);
}}
}
int lca(int x,int y)
{
int ans=inf;
if(deep[x]<deep[y])swap(x,y);
int d=deep[x]-deep[y];
for(int i=;(<<i)<=d;i++)
if((<<i)&d)ans=min(ans,ms[x][i]),x=f[x][i];
// printf("lca=%d\n",x);
if(x==y)return ans;
for(int i=;i>=;i--)
if(f[x][i]!=f[y][i])
ans=min(ans,min(ms[x][i],ms[y][i])),
x=f[x][i],y=f[y][i];//printf("lca=%d\n",f[x][0]);
if(f[x][]==)return -;
return (ans=min(ans,min(ms[x][],ms[y][])));
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
insert(u,v,w);
insert(v,u,w);
}
sort(eo+,eo+cnt+,cmp);
for(int i=;i<=n;i++)fa[i]=i;
for(int i=;i<=cnt;i++)
{
int u=eo[i].from,v=eo[i].to;
// printf("%d %d fa[5]=%d\n",u,v,fa[5]);
if(getfa(u)!=getfa(v))
{
fa[fa[u]]=fa[v];
// printf("[]%d %d\n",u,v);
ins(u,v,eo[i].w);
ins(v,u,eo[i].w);
}
}
for(int i=;i<=n;i++)
if(!ok[getfa(i)])ok[fa[i]]=,ins(,fa[i],inf);
// for(int i=1;i<=tot;i++)printf("[]%d %d %d\n",e[i].from,e[i].to,e[i].w);
dfs();
scanf("%d",&q);
for(int i=;i<=q;i++)
{
int x,y;
scanf("%d%d",&x,&y);
int ans=lca(x,y);
if(ans==-)printf("-1\n");
else printf("%d\n",ans);
}
return ;
}
【NOIP】提高组2013 货车运输的更多相关文章
- NOIP提高组 2013货车运输
觉得题目水的离开 不屑的大佬请离开 不会图论的请离开 ……. 感谢您贡献的访问量 ————————————华丽的分割线———————————— 题面: 题目描述 A 国有 n 座城市,编号从 1 到 ...
- 题解 【luoguP1967 NOIp提高组2013 货车运输】
题目链接 题解 题意 给你一个无向图,求两个点之间的一条路径,使路径上的最小值最大 算法:Kruskal最大生成树+倍增lca 分析 首先容易知道,答案一定在该图的最大生成树上 之后问题便转换成了树上 ...
- 【NOIP2013提高组】货车运输
货车运输 (truck.cpp/c/pas) [问题描述] A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有q辆货车在运输货物,司机们想知道每辆 ...
- 洛谷P1967 [NOIP2013提高组Day1T2]货车运输
P1967 货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过 ...
- 洛谷P1966 火柴排队[NOIP提高组2013]
我确信我应该是做过这道题……就当再写一遍好了. 贪心思想,一番证明得出a和b数组中最小对最小,次小对次小……时解最优.那么先处理出a,b之间的对应关系,然后按照该关系求a或者b的逆序对数量就是答案 / ...
- NOIP提高组2013 D2T3 【华容道】
某王 老师给我们考了一场noip2013的真题...心态爆炸! 题目大意: 有一个n*m的棋盘,每个格子上都有一个棋子,有些格子上的棋子能够移动(可移动的棋子是固定的),棋盘中有一个格子是空的,仍何 ...
- NOIP 2013 货车运输【Kruskal + 树链剖分 + 线段树 】【倍增】
NOIP 2013 货车运输[树链剖分] 树链剖分 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在 ...
- NOIP提高组2004 合并果子题解
NOIP提高组2004 合并果子题解 描述:在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消 ...
- 计蒜客 NOIP 提高组模拟竞赛第一试 补记
计蒜客 NOIP 提高组模拟竞赛第一试 补记 A. 广场车神 题目大意: 一个\(n\times m(n,m\le2000)\)的网格,初始时位于左下角的\((1,1)\)处,终点在右上角的\((n, ...
随机推荐
- 蜗牛慢慢爬 LeetCode 1.Two Sum [Difficulty: Easy]
题目 Given an array of integers, return indices of the two numbers such that they add up to a specific ...
- Maven的setting配置文件
一.Maven的setting配置文件 和 在Eclipse中对Maven的正确配置. 1.Maven的配置文件(Maven的安装目录/conf/settings.xml ) 和 Maven仓库下(默 ...
- 对mysql联合索引中的字段进行合理排序
在MySQL的where条件中,有时会用到很多的条件,通常为了加快速度会把这些字段放到联合索引中,可以更快的提高搜索速度: 但是对联合索引中字段顺序的合理排序,便更能提高速度 例子:select * ...
- CDN加速-内容分发网络
内容分发网络 (互联网技术) 编辑 CDN的全称是Content Delivery Network,即内容分发网络.其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输 ...
- 【C++】不要在构造函数或析构函数内调用虚函数
这个问题来自于<Effective C++>条款9:永远不要在构造函数或析构函数中调用虚函数 . 假设有如下代码: class Transaction {// 所有交易的基类 public ...
- 【计算机网络】NAT:网络地址转换
NAT(Network Address Translation,网络地址转换)是1994年提出的.当在专用网内部的一些主机本来已经分配到了本地IP地址(即仅在本专用网内使用的专用地址),但现在又想和因 ...
- [BZOJ1503][NOI2004]郁闷的出纳员 无旋Treap
1503: [NOI2004]郁闷的出纳员 Time Limit: 5 Sec Memory Limit: 64 MB Description OIER公司是一家大型专业化软件公司,有着数以万计的员 ...
- [TJOI2008]彩灯 线性基
题面 题面 题解 题意:给定n个01串,求互相异或能凑出多少不同的01串. 线性基的基础应用. 对于线性基中的01串,如果我们取其中一些凑成一个新的01串,有一个重要的性质:任意2个不同方案凑出的01 ...
- hdu4554 A Famous Game 概率期望
题面 题意:n个球,2种颜色,可能有0~n个红球,每种情况的概率相同.现在从箱子里取出了$p$个球,其中有$Q$个是红球,问现在再取一个球是红球的概率为多少? 题解:因为0 ~ n的概率相同,所以每个 ...
- 洛谷 P2258 子矩阵
题目描述 给出如下定义: 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵. 例如,下面左图中选取第2.4行和第2.4.5列交叉位置的元素 ...