description

某国有n座城市,这些城市之间通过m条单向道路相连,已知每条道路的长度。

不过,小X只对其中k座城市感兴趣。

为了更好地规划模拟旅行路线,提升模拟旅行的体验,小X想要知道他感兴趣的城市之间两两最短路的最小值(即在他感兴趣的城市中,最近的一对的最短距离)。

作为一个肥宅,小X根本懒得写程序来解决这道问题,于是他把这个问题丢给了你。


J 国有 nn 座城市,这些城市之间通过 mm 条单向道路相连,已知每条道路的长度。

一次,居住在 J 国的 Rainbow 邀请 Vani 来作客。不过,作为一名资深的旅行者,Vani 只对 J 国的 kk 座历史悠久、自然风景独特的城市感兴趣。

为了提升旅行的体验,Vani 想要知道他感兴趣的城市之间「两两最短路」的最小值(即在他感兴趣的城市中,最近的一对的最短距离)。

也许下面的剧情你已经猜到了——Vani 这几天还要忙着去其他地方游山玩水,就请你帮他解决这个问题吧。


analysis

  • 对于所有关键点开始跑最短路,原图和反图分别跑一次,记为\(dis_i,dis1_i\)

  • 记录下\(dij\)里每个点从哪一个关键点转移得来,记为\(from_i,from1_i\)

  • 枚举一条边,如果边的两端点的\(from_x≠from_y\),此时可以拿\(dis_x+dis1_y+len\)更新答案

  • 因为\(from_x≠from_y\),所以两端点是从不同关键点走到,说明该边可能在两个关键点的最短路上


  • 还有一种更妙的做法,不过\(SPFA\)弄不了,我还没实现

  • 建立超级源向所有关键点连\(0\)边,然后从超级源跑最短路和次短路

  • 关键点的最短路当然是\(0\),次短路的意义是什么呢

  • 其实某关键点的次短路一定是经过另一个关键点走到它的最短路

  • 答案取次短路的最小值就可以了,感觉确实妙


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#define MAXN 300005
#define MAXM 3000005
#define ha 1926081719491001
#define ll long long
#define reg register ll
#define max(x,y) ((x>y)?(x):(y))
#define min(x,y) ((x<y)?(x):(y))
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define rep(i,a) for (reg i=last[a];i;i=next[i])
#define rep1(i,a) for (reg i=last1[a];i;i=next1[i]) using namespace std; ll last[MAXM],next[MAXM],tov[MAXM],len[MAXM];
ll last1[MAXM],next1[MAXM],tov1[MAXM],len1[MAXM];
ll a[MAXN],dis[MAXN],dis1[MAXN],from[MAXN],from1[MAXN];
ll n,m,k,tot,tot1,ans=ha;
ll edge[MAXM][3];
bool bz[MAXN]; struct node
{
ll x,y;
bool operator<(const node &a)const{return a.y<y;}
};
priority_queue<node>q; inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline void link(ll x,ll y,ll z){next[++tot]=last[x],last[x]=tot,tov[tot]=y,len[tot]=z;}
inline void link1(ll x,ll y,ll z){next1[++tot1]=last1[x],last1[x]=tot1,tov1[tot1]=y,len1[tot1]=z;}
inline void dijkstra()
{
memset(dis,100,sizeof(dis));
memset(bz,0,sizeof(bz));
fo(i,1,k)q.push((node){a[i],dis[a[i]]=0}),from[a[i]]=a[i];
while (!q.empty())
{
node now=q.top();q.pop();
if (bz[now.x])continue;bz[now.x]=1;
rep(i,now.x)if (dis[now.x]+len[i]<dis[tov[i]])
{
dis[tov[i]]=dis[now.x]+len[i],from[tov[i]]=from[now.x];
q.push((node){tov[i],dis[tov[i]]});
}
}
}
inline void dijkstra1()
{
memset(dis1,100,sizeof(dis1));
memset(bz,0,sizeof(bz));
fo(i,1,k)q.push((node){a[i],dis1[a[i]]=0}),from1[a[i]]=a[i];
while (!q.empty())
{
node now=q.top();q.pop();
if (bz[now.x])continue;bz[now.x]=1;
rep1(i,now.x)if (dis1[now.x]+len1[i]<dis1[tov1[i]])
{
dis1[tov1[i]]=dis1[now.x]+len1[i],from1[tov1[i]]=from1[now.x];
q.push((node){tov1[i],dis1[tov1[i]]});
}
}
}
int main()
{
freopen("tour.in","r",stdin);
freopen("tour.out","w",stdout);
n=read(),m=read(),k=read();
fo(i,1,m)
{
ll x=read(),y=read(),z=read();
edge[i][0]=x,edge[i][1]=y,edge[i][2]=z;
link(x,y,z),link1(y,x,z);
}
fo(i,1,k)a[i]=read();
dijkstra(),dijkstra1();
fo(i,1,m)if (from[edge[i][0]]!=from1[edge[i][1]])
ans=min(ans,dis[edge[i][0]]+dis1[edge[i][1]]+edge[i][2]);
printf("%lld\n",ans);
return 0;
}
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#define MAXN 300005
#define MAXM 3000005
#define ha 1926081719491001
#define ll long long
#define reg register ll
#define max(x,y) ((x>y)?(x):(y))
#define min(x,y) ((x<y)?(x):(y))
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define rep(i,a) for (reg i=last[a];i;i=next[i])
#define rep1(i,a) for (reg i=last1[a];i;i=next1[i]) using namespace std; ll last[MAXM],next[MAXM],tov[MAXM],len[MAXM];
ll last1[MAXM],next1[MAXM],tov1[MAXM],len1[MAXM];
ll a[MAXN],dis[MAXN],dis1[MAXN],from[MAXN],from1[MAXN];
ll n,m,k,T,tot,tot1,ans=ha;
ll edge[MAXM][3];
bool bz[MAXN]; struct node
{
ll x,y;
bool operator<(const node &a)const{return a.y<y;}
};
priority_queue<node>q; inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline void link(ll x,ll y,ll z){next[++tot]=last[x],last[x]=tot,tov[tot]=y,len[tot]=z;}
inline void link1(ll x,ll y,ll z){next1[++tot1]=last1[x],last1[x]=tot1,tov1[tot1]=y,len1[tot1]=z;}
inline void dijkstra()
{
memset(dis,100,sizeof(dis));
memset(bz,0,sizeof(bz));
fo(i,1,k)q.push((node){a[i],dis[a[i]]=0}),from[a[i]]=a[i];
while (!q.empty())
{
node now=q.top();q.pop();
if (bz[now.x])continue;bz[now.x]=1;
rep(i,now.x)if (dis[now.x]+len[i]<dis[tov[i]])
dis[tov[i]]=dis[now.x]+len[i],from[tov[i]]=from[now.x],q.push((node){tov[i],dis[tov[i]]});
}
}
inline void dijkstra1()
{
memset(dis1,100,sizeof(dis1));
memset(bz,0,sizeof(bz));
fo(i,1,k)q.push((node){a[i],dis1[a[i]]=0}),from1[a[i]]=a[i];
while (!q.empty())
{
node now=q.top();q.pop();
if (bz[now.x])continue;bz[now.x]=1;
rep1(i,now.x)if (dis1[now.x]+len1[i]<dis1[tov1[i]])
dis1[tov1[i]]=dis1[now.x]+len1[i],from1[tov1[i]]=from1[now.x],q.push((node){tov1[i],dis1[tov1[i]]});
}
}
int main()
{
T=read();
while (T--)
{
memset(last,0,sizeof(last)),memset(last1,0,sizeof(last1));
memset(next,0,sizeof(next)),memset(next1,0,sizeof(next1));
memset(tov,0,sizeof(tov)),memset(tov1,0,sizeof(tov1)),tot=0;
memset(len,0,sizeof(len)),memset(len1,0,sizeof(len1)),tot1=0;
memset(from,0,sizeof(from)),memset(from1,0,sizeof(from1));
n=read(),m=read(),k=read(),ans=ha;
fo(i,1,m)
{
ll x=read(),y=read(),z=read();
edge[i][0]=x,edge[i][1]=y,edge[i][2]=z;
link(x,y,z),link1(y,x,z);
}
fo(i,1,k)a[i]=read();
dijkstra(),dijkstra1();
fo(i,1,m)if (from[edge[i][0]]!=from1[edge[i][1]])
ans=min(ans,dis[edge[i][0]]+dis1[edge[i][1]]+edge[i][2]);
printf("%lld\n",ans);
}
return 0;
}

【JZOJ6419】模拟旅行&【BZOJ5506】【luoguP5304】旅行者的更多相关文章

  1. GDOI2014模拟 旅行【SPFA】

    旅行(travel) 从前有一位旅者,他想要游遍天下所有的景点.这一天他来到了一个神奇的王国:在这片土地上,有n个城市,从1到n进行编号.王国中有m条道路,第i条道路连接着两个城市ai,bi,由于年代 ...

  2. bzoj5506:[gzoi2019]旅行者

    传送门 正反两边dijkstra染色,然后枚举一下边,求出最小值就好啦 代码: #include<cstdio> #include<iostream> #include< ...

  3. BZOJ 3531: [Sdoi2014]旅行 [树链剖分]

    3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1685  Solved: 751[Submit][Status] ...

  4. 【bzoj3531】 [SDOI2014]旅行

    题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们 ...

  5. Bzoj3531: [Sdoi2014]旅行

    Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1698  Solved: 758 Description S国有N个城市,编号从1到N.城市间用N-1 ...

  6. 【BZOJ3531】[Sdoi2014]旅行 树链剖分+动态开点线段树

    [BZOJ3531][Sdoi2014]旅行 Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天 ...

  7. bzoj 3531 [Sdoi2014]旅行(树链剖分,线段树)

    3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 876  Solved: 446[Submit][Status][ ...

  8. bzoj 3531: [Sdoi2014]旅行

    Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. ...

  9. 【BZOJ3531】旅行(树链剖分,线段树)

    [BZOJ3531]旅行(树链剖分,线段树) 题面 Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教 ...

随机推荐

  1. Android 使用android-support-multidex解决Dex超出方法数的限制问题,让你的应用不再爆棚(转)

    如有转载,请声明出处: 时之沙: http://blog.csdn.net/t12x3456    (来自时之沙的csdn博客) 随着应用不断迭代,业务线的扩展,应用越来越大(比如集成了各种第三方sd ...

  2. TCP协议中的三次握手和四次挥手(图解)(转)

    转自:http://blog.csdn.net/whuslei/article/details/6667471 建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看 ...

  3. CSIC_716_20191209【并发编程---GIL和协程】

    GIL   Global Interpreter Lock 全局解释锁 GIL对含IO的任务来说,会出现不能保证数据安全的情况.如下: from threading import Thread fro ...

  4. php 中 instanceof 操作符

    "instanceof"操作符的使用非常简单,它用两个参数来完成其功能.第一个参数是你想要检查的对象,第二个参数是类名(事实上是一个接口名),用于确定是否这个对象是相应类的一个实例 ...

  5. Spring Boot 2.0 常见问题总结(一)

    SpringBoot2.x 依赖环境和版本新特性说明 依赖版本 jdk8 以上, Springboot2.x 用 JDK8 , 因为底层是 Spring framework5 . jar 包方式运行 ...

  6. HTML5的新增功能有哪些?

    HTML5 将成为 HTML.XHTML 以及 HTML DOM 的新标准. 新的功能: 1.用于绘画的 canvas 元素 2.用于媒介回放的 video 和 audio 元素 3.对本地离线存储的 ...

  7. 用javascript插入<style>样式

    function addCSS(cssText){ var style = document.createElement('style'), //创建一个style元素 head = document ...

  8. lnmp mysql高负载优化

    mysql负载会造成cpu占用高的问题如果没启用innodb的话 用这个配置/usr/local/mysql/share/mysql/my-large.cnf 替换/etc/my.cnf 也可参考如下 ...

  9. [NOIP模拟测试12]题解

    A. 找规律题.儿子的编号减去 小于它编号的最大的fibonacci数 即可得到它父亲的编号. 然后两个节点都暴力上跳就好了.预处理一下fibonacci数,每次二分查找即可. #include< ...

  10. [NOIP模拟测试7]visit 题解(组合数学+CRT+Lucas定理)

    Orz 因为有T的限制,所以不难搞出来一个$O(T^3)$的暴力dp 但我没试 据说有30分? 正解的话显然是组合数学啦 首先$n,m$可能为负,但这并没有影响, 我们可以都把它搞成正的 即都看作向右 ...