【BZOJ1880】[Sdoi2009]Elaxia的路线(最短路)

题面

BZOJ

洛谷

题解

假装我们知道了任意两点间的最短路,那么我们怎么求解答案呢?

不难发现公共路径一定是一段连续的路径(如果不连续那么显然可以把中间分开的那段变成一样路径)。

这样子我们只需要\(O(n^2)\)枚举这个路径的起点和终点\(check\)一下就可以知道答案了。

然而并没有办法求任意两点之间的最短路,因为这样子是\(O(n^3)\)的。并不要认为对于每个点跑一遍最短路就行了,\(SPFA\)不说了,它死了。\(Dijkstra\)的复杂度是\(O((n+m)logm)\)的,如果\(m=n^2\)还不如\(Floyd\)。

大概的代码如下,我是对于每一个点跑了一遍\(Dij\)(雾

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define MAX 1550
#define pi pair<int,int>
#define mp make_pair
#define fr first
#define sd second
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
struct Line{int v,next,w;}e[MAX*MAX*2];
int h[MAX],cnt=1;
inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w};h[u]=cnt++;}
int dis[MAX][MAX];
int n,m,S1,S2,T1,T2,ans;
bool vis[MAX];
void SPFA(int S,int *dis)
{
for(int i=1;i<=n;++i)dis[i]=1e9,vis[i]=false;
priority_queue<pi,vector<pi>,greater<pi> > Q;
Q.push(mp(0,S));dis[S]=0;
while(!Q.empty())
{
pi u=Q.top();Q.pop();
if(vis[u.sd])continue;vis[u.sd]=true;
for(int i=h[u.sd];i;i=e[i].next)
if(dis[e[i].v]>u.fr+e[i].w)
{
dis[e[i].v]=u.fr+e[i].w;
Q.push(mp(dis[e[i].v],e[i].v));
}
}
}
int Dis1(int i,int j){return dis[S1][i]+dis[i][j]+dis[j][T1];}
int Dis2(int i,int j){return dis[S2][i]+dis[i][j]+dis[j][T2];}
int main()
{
n=read();m=read();
S1=read(),T1=read(),S2=read(),T2=read();
for(int i=1;i<=m;++i)
{
int u=read(),v=read(),w=read();
Add(u,v,w);Add(v,u,w);
}
for(int i=1;i<=n;++i)SPFA(i,dis[i]);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
if(i!=j)
{
if(Dis1(i,j)>dis[S1][T1]&&Dis1(j,i)>dis[S1][T1])continue;
if(Dis2(i,j)>dis[S2][T2]&&Dis2(j,i)>dis[S2][T2])continue;
ans=max(ans,dis[i][j]);
}
printf("%d\n",ans);
return 0;
}

首先,对于钦定的起点,我们到达终点一定是沿着最短路径\(DAG\)移动,那么我们考虑对于起点构建最短路径\(DAG\),将几个\(DAG\)重叠之后显然是要求的是\(S1\rightarrow T1\)的一条路径上的最长的、在两个最短路径\(DAG\)中都出现过的链。

那么我们把同时出现在两个\(DAG\)中的边全部拿出来建图,跑一个\(DAG\)上最长链就好了。

我代码写的有点冗长。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define MAX 1550
#define pi pair<int,int>
#define mp make_pair
#define fr first
#define sd second
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
struct Line{int v,next,w;}e[1000000];
int h[MAX],cnt=2,dg[MAX];
inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w};h[u]=cnt++;}
vector<int> E[MAX],W[MAX];
int dis[MAX][MAX];
int n,m,S1,S2,T1,T2,ans;
bool vis[MAX];
void SPFA_heap(int S,int *dis)
{
for(int i=1;i<=n;++i)dis[i]=1e9,vis[i]=false;
priority_queue<pi,vector<pi>,greater<pi> > Q;
Q.push(mp(0,S));dis[S]=0;
while(!Q.empty())
{
pi u=Q.top();Q.pop();
if(vis[u.sd])continue;vis[u.sd]=true;
for(int i=h[u.sd];i;i=e[i].next)
if(dis[e[i].v]>u.fr+e[i].w)
{
dis[e[i].v]=u.fr+e[i].w;
Q.push(mp(dis[e[i].v],e[i].v));
}
}
}
int S[MAX],f[MAX],top;
void Topsort()
{
queue<int> Q;
for(int i=1;i<=n;++i)if(!dg[i])Q.push(i);
while(!Q.empty())
{
int u=Q.front();Q.pop();S[++top]=u;
for(int i=0,l=E[u].size();i<l;++i)
if(!--dg[E[u][i]])Q.push(E[u][i]);
}
for(int i=top;i;--i)
for(int j=0,l=E[S[i]].size();j<l;++j)
f[S[i]]=max(f[S[i]],f[E[S[i]][j]]+W[S[i]][j]);
for(int i=1;i<=top;++i)ans=max(ans,f[S[i]]);
}
int main()
{
n=read();m=read();
S1=read(),T1=read(),S2=read(),T2=read();
for(int i=1;i<=m;++i)
{
int u=read(),v=read(),w=read();
Add(u,v,w);Add(v,u,w);
}
SPFA_heap(S1,dis[S1]);SPFA_heap(T1,dis[T1]);SPFA_heap(S2,dis[S2]);SPFA_heap(T2,dis[T2]);
for(int u=1;u<=n;++u)
for(int i=h[u];i;i=e[i].next)
if(i&1)
{
int u=e[i].v,v=e[i^1].v;
if(min(dis[S1][u]+dis[T1][v]+e[i].w,dis[S1][v]+dis[T1][u]+e[i].w)>dis[S1][T1])continue;
if(min(dis[S2][u]+dis[T2][v]+e[i].w,dis[S2][v]+dis[T2][u]+e[i].w)>dis[S2][T2])continue;
if(dis[S1][u]+dis[T1][v]+e[i].w==dis[S1][T1])E[u].push_back(v),W[u].push_back(e[i].w),dg[v]+=1;
else E[v].push_back(u),W[v].push_back(e[i].w),dg[u]+=1;
}
Topsort();
printf("%d\n",ans);
return 0;
}

【BZOJ1880】[Sdoi2009]Elaxia的路线(最短路)的更多相关文章

  1. BZOJ1880:[SDOI2009]Elaxia的路线(最短路,拓扑排序)

    Description 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间.Elaxia和w**每天都要奔波于宿舍和实验室之间, ...

  2. 【BZOJ1880】[Sdoi2009]Elaxia的路线 最短路+DP

    [BZOJ1880][Sdoi2009]Elaxia的路线 Description 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起 ...

  3. BZOJ1880: [Sdoi2009]Elaxia的路线(最短路)

    1880: [Sdoi2009]Elaxia的路线 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 2049  Solved: 805 题目链接:https ...

  4. 【BZOJ1880】[SDOI2009]Elaxia的路线 (最短路+拓扑排序)

    [SDOI2009]Elaxia的路线 题目描述 最近,\(Elaxia\)和\(w**\)的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. \(El ...

  5. BZOJ 1880: [Sdoi2009]Elaxia的路线( 最短路 + dp )

    找出同时在他们最短路上的边(dijkstra + dfs), 组成新图, 新图DAG的最长路就是答案...因为两人走同一条路但是不同方向也可以, 所以要把一种一个的s,t换一下再更新一次答案 ---- ...

  6. bzoj1880: [Sdoi2009]Elaxia的路线(spfa,拓扑排序最长路)

    1880: [Sdoi2009]Elaxia的路线 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 1944  Solved: 759[Submit][St ...

  7. Luogu P2149 [SDOI2009]Elaxia的路线(最短路+记忆化搜索)

    P2149 [SDOI2009]Elaxia的路线 题意 题目描述 最近,\(Elaxia\)和\(w**\)的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们必须合理地安排两个人在一起的 ...

  8. [luogu2149][bzoj1880][SDOI2009]Elaxia的路线【拓扑排序+最短路+DP】

    题目描述 最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. Elaxia和w每天都要奔波于宿舍和实验室之间,他们 希望在节约时间 ...

  9. BZOJ1880 [Sdoi2009]Elaxia的路线 【最短路 + dp】

    题目 最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间.Elaxia和w每天都要奔波于宿舍和实验室之间,他们 希望在节约时间的前提 ...

  10. [BZOJ1880] [Sdoi2009] Elaxia的路线 (SPFA & 拓扑排序)

    Description 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间.Elaxia和w**每天都要奔波于宿舍和实验室之间, ...

随机推荐

  1. 搭建SpringBoot+dubbo+zookeeper+maven框架(二)

    上一篇文章是关于搭建SpringBoot+dubbo+zookeeper+maven框架的,但是里面的功能还不够完善,今天就日志管理方面做一些改善. 下了demo的网友可能会发现项目在启动时会有警告: ...

  2. 2017NOIP游记

    记得去年这个时候,大概刚接触OI.没想到时间这么快,第一次2017NOIP之旅已经结束.初测成绩出来了,100+100+95+50=345,有浙江三十几名(@Cptraser 机房370大佬).总体感 ...

  3. 面试3——java集合类面试题总结

    1.总结一下啊hashmap和hashtable的知识点? 1)关于hashmap的说法 HashMap实际上是一个“链表散列”的数据结构,在jdk1.8中添加了红黑树.HashMap底层结构是一个数 ...

  4. [Socket]Socket聊天小程序

    一个简单是Socket聊天小程序,读写操作在不同的线程中.服务器端采用线程池. 1.Server import java.io.IOException; import java.net.ServerS ...

  5. 2016年总结 - Java程序员

    一 . 技术积累 (1)代码规范 1.1.1.通常的模块分布:一般如果你要实现一个web应用,你从后台将数据展示到前端页面,在一个比较大的公司,你少不了跟其他项目有交集(你调用他的接口,他依赖你的接口 ...

  6. R绘图 第七篇:绘制条形图(ggplot2)

    使用geom_bar()函数绘制条形图,条形图的高度通常表示两种情况之一:每组中的数据的个数,或数据框中列的值,高度表示的含义是由geom_bar()函数的参数stat决定的,stat在geom_ba ...

  7. 如何在命令长度受限的情况下成功get到webshell(函数参数受限突破、mysql的骚操作)

    0x01 问题提出 还记得上篇文章记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门),我们讲到了一些PHP的一些如何巧妙地绕过数字和字母受限的技巧,今天我要给大家分享的是如 ...

  8. 使用Zabbix服务端本地邮箱账号发送报警邮件及指定报警邮件操作记录

    邮件报警有两种情况:1)Zabbix服务端只是单纯的发送报警邮件到指定邮箱,发送报警邮件的这个邮箱账号是Zabbix服务端的本地邮箱账号(例如:root@localhost.localdomain), ...

  9. 网络编程学习笔记:Socket编程

    文的主要内容如下: 1.网络中进程之间如何通信? 2.Socket是什么? 3.socket的基本操作 3.1.socket()函数 3.2.bind()函数 3.3.listen().connect ...

  10. 美食应用 吃了么 beta 测试报告

    为了更好的测试我们应用的兼容性和性能,我们借助了网上的平台Testin云测和百度MTC平台来测试我们的应用,一下是我们的测试结果. 一.兼容性测试 我们对119台终端机器进行了测试,通过测试的有99台 ...