P1967 货车运输

题目描述

A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,从一个地方到另一个地方最多能运多重的货物。

说明

对于 100%的数据,0 < 城市数n < 10,000,0 < 道路数m < 50,000,0 < 询问数q< 30,000,0 ≤ 限重z ≤ 100,000。


鉴于这是个稀疏图,我们用kruskal。

最小生成树有一个定理,就是边集中最大的边最小

那么我们魔改一下kruskal使它变成求最大生成树,就有最小边最大的定理。

之后就可以通过一些手段来处理造出来的生成树了

树链剖分辣么长,懒得打

所以博主这儿用的倍增

f1[i][j]表示i点往上跳2^j距离到达的点

f2[i][j]表示i点往上跳2^j距离的路径上的最小值

就可以暴力求LCA辣啊哈哈哈哈

这里推荐一个更快的大佬code-> http://www.cnblogs.com/xzz_233/p/7614189.html .

代码蒯上

#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
inline int gotcha()
{
register int _a=0;bool _b=1;register char _c=getchar();
while(_c<'0' || _c>'9'){if(_c=='-')_b=0;_c=getchar();}
while(_c>='0' && _c<='9')_a=_a*10+_c-48,_c=getchar();
return _b?_a:-_a;
}
const int _ = 10002;
using namespace std;
struct edge{int to,ne,len;edge(){to=ne=len=0;}}e[10*_];
struct sav
{
int fr,to,len;sav(){fr=to=len=0;}
const bool operator < (const sav &b)const{return len>b.len;}
}tp[5*_];
int he[_],ecnt=0,dep[_],f1[_][18],f2[_][18],n,m,fa[_],gfa[_];
void add(int fr,int to,int len)
{e[++ecnt].to=to,e[ecnt].len=len,e[ecnt].ne=he[fr],he[fr]=ecnt;}
int finder(int a){return gfa[a]!=a?gfa[a]=finder(gfa[a]):a;}
void link(int a,int b){gfa[finder(b)]=finder(a);}
void plant(int a)
{
for(int i=he[a],j;i;i=e[i].ne)
{
j=e[i].to;if(j==fa[a])continue;
fa[j]=a,f1[j][0]=a,f2[j][0]=e[i].len,dep[j]=dep[a]+1,plant(j);
}
}
int driver(int st,int ta)
{
register int i,mi=2e9;
if(dep[st]>dep[ta])
for(i=16;i>=0;i--)if(f1[st][i]!=0 && dep[f1[st][i]]>=dep[ta])
mi=min(mi,f2[st][i]),st=f1[st][i];
if(dep[ta]>dep[st])
for(i=16;i>=0;i--)if(f1[ta][i]!=0 && dep[f1[ta][i]]>=dep[st])
mi=min(mi,f2[ta][i]),ta=f1[ta][i];
if(st==ta)return mi;
for(i=16;i>=0;i--)if(f1[st][i]!=f1[ta][i])
mi=min(mi,min(f2[st][i],f2[ta][i])),st=f1[st][i],ta=f1[ta][i];
return min(mi,min(f2[st][0],f2[ta][0]));
}
int main()
{
register int i,j,k;
n=gotcha(),m=gotcha();
for(i=1;i<=n;i++)gfa[i]=i;
for(i=1;i<=m;i++)tp[i].fr=gotcha(),tp[i].to=gotcha(),tp[i].len=gotcha();
sort(tp+1,tp+m+1);
for(i=1;i<=m;i++)
if(finder(tp[i].fr)!=finder(tp[i].to))
{
link(tp[i].fr,tp[i].to);
add(tp[i].fr,tp[i].to,tp[i].len),add(tp[i].to,tp[i].fr,tp[i].len);
}
for(i=1;i<=n;i++)if(i==gfa[i])fa[i]=i,dep[i]=1,plant(i);
for(i=1;i<=16;i++)
for(j=1;j<=n;j++)
{
f1[j][i]=f1[f1[j][i-1]][i-1];
f2[j][i]=min(f2[j][i-1],f2[f1[j][i-1]][i-1]);
}
i=gotcha();
while(i--)
{
j=gotcha(),k=gotcha();
printf("%d\n",(finder(j)==finder(k)?driver(j,k):-1));
}
return 0;
}

最新文章

  1. Echarts动态加载后台数据
  2. ExtJS入门教程03,form中怎能没有validation
  3. Ubuntu配置网络命令(转载)
  4. AFNetworking3.0出现Error Domain=com.alamofire.error.serialization.response Code=-1016 &quot;Request failed: unacceptable
  5. 黄聪:Microsoft Enterprise Library 5.0 系列教程(三) Validation Application Block (高级)
  6. toString方法的用处
  7. codeforce round#466(div.2) B. Our Tanya is Crying Out Loud
  8. 我的redis入门之路
  9. Linux 我的常用命令记录
  10. nmap 常用命令
  11. CSS面试复习(二):CSS的使用
  12. cordova获取app版本信息插件的使用:cordova-plugin-app-version
  13. PAT 1005 继续(3n+1)猜想 (25)(代码)
  14. Java面试题—初级(9)
  15. VS2010自行编译OpenCV2.4.4时缺少python27_d.lib的解决方法
  16. Elasticsearch学习之ES节点类型以及各种节点的分工
  17. android stream media
  18. 35. CentOS-6.3安装拼音输入法
  19. 33. Search in Rotated Sorted Array旋转数组二分法查询
  20. RabbitMQ(二):理解消息通信RabbitMQ

热门文章

  1. IOC的使用
  2. ServletContext--HttpServletResponse--web项目执行流程
  3. &lt;Android 应用 之路&gt; 天气预报(二)
  4. Android ORM对象关系映射之GreenDAO建立多表关联
  5. mac不限速下载百度网盘
  6. 【LeetCode】9 Palindrome Number 回文数判定
  7. Unity中实现全局管理类的几种方式
  8. Java设计模式之责任链模式、职责链模式
  9. codeforces Gym 100286J Javanese Cryptoanalysis (二染色)
  10. Android(java)学习笔记133:Eclipse中的控制台不停报错Can&#39;t bind to local 8700 for debugger