Description

在一条边上求一个点,使得这个点到所有点的最长的最短距离 最短. \(n \leqslant 10^5\)

Sol

Dijkstra+扫描线+单调队列.

这个好像叫什么最小直径生成树?不过变成了在一个边上...

对于一个点,我们可以求出当分割点在哪个位置的时候,它应该到 \(A\) ,什么时候它应该到 \(B\) .

\(dis_A(i)+t \leqslant dis_B(j)+(dis_{AB}-t)\)

移项得 \(t\leqslant \frac{dis_B(i)-dis_A(i)+dis_{AB}}{2}\)

这样就把线段 \(AB\) 分成了几个区间,枚举区间,然后分别用两个单调队列维护一下到分割点左右到 \(A,B\) 距离的最大值.

对于一个区间,我们可以 \(O(1)\) 的求出在这个区间应该选择哪个点作为分割点,因为两边的点都是确定的最大距离也知道,然后统计答案就可以了.

Code

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<functional>
#include<iostream>
using namespace std; #define mpr(a,b) make_pair(a,b)
#define debug(a) cout<<#a<<"="<<a<<" "
#define Fst first
#define Sec second
typedef long long LL;
typedef pair< LL,int > pr;
const int N = 100005; LL T,n,m,k,A,B,X;
vector<pr> g[N];
LL ds[N],dt[N];
pair< double,int > p[N];double lm[N];
pair< double,double > ans;
int q1[N],q2[N],h1,h2,t1,t2;
priority_queue<pr,vector<pr>,greater<pr> > q; inline LL in(LL x=0,char ch=getchar()){ while(ch>'9' || ch<'0') ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x; }
void clr(){
t1=t2=0,h1=h2=1;ans=mpr(1e18,-1);
for(int i=0;i<N;i++) g[i].clear();
}
void Up(int i,int j){
double l=max(min((X+ds[j]+dt[i])/2.0-ds[j],lm[j]),lm[i]),tmp=max(ds[j]+l,X-l+dt[i]);
// debug(i),debug(j),debug(dt[i]),debug(ds[j]),debug((X+ds[j]+dt[i])/2.0-dt[i]),debug(lm[i]),debug(lm[j]),debug(l),debug(tmp)<<endl;
if(tmp < ans.Fst||(tmp == ans.Fst && l<ans.Sec)) ans=mpr(tmp,l);
}
void Dijkstra(int s,LL *d){
static bool b[N];memset(b,0,sizeof(b));for(int i=1;i<=n;i++) d[i]=1000000000000000000LL;
d[s]=0,q.push(mpr(0,s));
for(int u;!q.empty();){
u=q.top().Sec,q.pop();if(b[u]) continue;b[u]=1;
for(int i=0;i<g[u].size();i++){
LL p=g[u][i].Fst;int v=g[u][i].Sec;
if(d[u]+p < d[v]) d[v]=d[u]+p,q.push(mpr(d[v],v));
}
}
}
int main(){
for(T=in();T--;){
clr();
n=in(),m=in(),k=in();
for(int i=1,u,v,x;i<=m;i++){
u=in(),v=in(),x=in();
g[u].push_back(mpr(x,v)),g[v].push_back(mpr(x,u));
if(i == k) A=u,B=v,X=x;
}
Dijkstra(A,ds),Dijkstra(B,dt); // cout<<X<<endl; // for(int i=1;i<=n;i++) cout<<ds[i]<<" ";cout<<endl;
// for(int i=1;i<=n;i++) cout<<dt[i]<<" ";cout<<endl; for(int i=1;i<=n;i++) p[i]=mpr((dt[i]-ds[i]+X)/2.0,i),lm[i]=(dt[i]-ds[i]+X)/2.0;
sort(p+1,p+n+1); // for(int i=1;i<=n;i++) printf("%lf %d\n",p[i].Fst,p[i].Sec); for(int i=1;i<=n;i++){
while(h2<=t2 && ds[q2[t2]] <= ds[p[i].Sec]) t2--;
q2[++t2]=p[i].Sec;
}
// cout<<ds[q2[h2]]+X<<endl;
ans=mpr(ds[q2[h2]],0);
for(int i=1,r;i<=n;i=r+1){
r=i;
while(p[r].Fst == p[r+1].Fst) r++;
/// debug(r)<<endl;
for(int j=i;j<=r;j++){ while(h1<=t1 && dt[q1[t1]] <= dt[p[j].Sec]) t1--;q1[++t1]=p[j].Sec; }
for(int j=i;j<=r;j++) if(q2[h2] == p[j].Sec) h2++;
// debug(q1[h1]),debug(q2[h2])<<endl;
Up(q1[h1],q2[h2]);
}
if(dt[q1[h1]]<ans.Fst) ans=mpr(dt[q1[h1]],X);
printf("%.5lf %.5lf\n",ans.Sec,ans.Fst);
}
return 0;
}

  

HackerRank savita-and-friends的更多相关文章

  1. 日常小测:颜色 && Hackerrank Unique_colors

    题目传送门:https://www.hackerrank.com/challenges/unique-colors 感谢hzq大神找来的这道题. 考虑点分治(毕竟是路经统计),对于每一个颜色,它的贡献 ...

  2. HackerRank "Square Subsequences" !!!

    Firt thought: an variation to LCS problem - but this one has many tricky detail. I learnt the soluti ...

  3. HackerRank "Minimum Penalty Path"

    It is about how to choose btw. BFS and DFS. My init thought was to DFS - TLE\MLE. And its editorial ...

  4. HackerRank "TBS Problem" ~ NPC

    It is marked as a NPC problem. However from the #1 code submission (https://www.hackerrank.com/Charl ...

  5. HackerRank Extra long factorials

    传送门 今天在HackerRank上翻到一道高精度题,于是乎就写了个高精度的模板,说是模板其实就只有乘法而已. Extra long factorials Authored by vatsalchan ...

  6. HackerRank "Lucky Numbers"

    Great learning for me:https://www.hackerrank.com/rest/contests/master/challenges/lucky-numbers/hacke ...

  7. HackerRank "Playing with numbers"

    This is 'Difficult' - I worked out it within 45mins, and unlocked HackerRank Algorithm Level 80 yeah ...

  8. HackerRank "The Indian Job"

    A sly knapsack problem in disguise! Thanks to https://github.com/bhajunsingh/programming-challanges/ ...

  9. HackerRank "Array and simple queries" !

    The most interesting, flexible and juicy binary tree problem I have ever seen. I learnt it from here ...

  10. HackerRank "Self Balancing Tree"

    Something to learn: Rotation ops in AVL tree does not require recursion. https://github.com/andreima ...

随机推荐

  1. CentOS7 Mini安装Oracle(图形化安装)

    以下操作在root用户下进行 1.mini版centos7没有ifconfig指令,可以如下操作 [root@localhost ~]# yum upgrade [root@localhost ~]# ...

  2. C++ Pointer-to-Member Selector

    http://www.codeguru.com/cpp/cpp/article.php/c17401/C-Tutorial-PointertoMember-Function.htm https://m ...

  3. OSX10.11 删除系统自带的软件

    之前一直用sudo rm - rf 系统的浏览器名字 正常删除safari 升级到10.11后,完全没作用了 需要关闭系统的什么安全模式 csrutil disable 再进入系统使用此命令可正常删除 ...

  4. 浅谈JavaScript中的事件

    引言 Html页面与JavaScript之间的交互是通过事件来完成的.事件,就是文档或者浏览器窗口中发生的一些特定的交互瞬间.可以使用侦听器(处理程序)来预订事件,以便事件发生时执行相应的代码.这在传 ...

  5. spring的PathMatchingResourcePatternResolver-通配符的Resource查找器

    PathMatchingResourcePatternResolver是一个通配符的Resource查找器,包括: /WEB-INF/*-context.xml com/mycompany/**/ap ...

  6. Inside the c++ object module 阅读摘要

    这本书是 Stanley B. Lippman于1996年所写,而最早的c++标准是 ISO/IEC 14882:1998[18],即C++98. Chapter 1: Object Lessons ...

  7. VPN添加静态路由表(指定程序或资源走VPN)

    在某此情况下,我们希望为VPN客户端指定线路,比如只有公司的资源或网站才使用VPN连接,其它的网络请求依然走他们自己的默认网关. 这种情况下,我们就需要给VPN客户端添加静态路由规则并取消VPN连接的 ...

  8. PHP基础 数组函数 的总结

    <?php /** * PHP基础 数组操作函数 * * 指针函数:[类似于数据库的游标] 见例1.1 * current($arr)/pos 返回当前指针指向的元素 * key($arr) 返 ...

  9. 【PHP面向对象(OOP)编程入门教程】4.如何抽象出一个类?

    上面已经介绍过了, 面向对象程序的单位就是对象,但对象又是通过类的实例化出来的,所以我们首先要做的就是如何来声明类, 做出来一个类很容易,只要掌握基本的程序语法定义规则就可以做的出来,那么难点在那里呢 ...

  10. Linux下安装和配置JDK与Tomcat(入门版)

    JDK路径:/usr/java/jdk1.6.0_25 Tomcat路径:/usr/local/apache-tomcat 1. 下载jdk6.0(选择“.rpm.bin”结尾的,6u25版本) ht ...