P2149 [SDOI2009]Elaxia的路线[最长公共路径]
题目描述
最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间。
Elaxia和w**每天都要奔波于宿舍和实验室之间,他们 希望在节约时间的前提下,一起走的时间尽可能的长。
现在已知的是Elaxia和w**所在的宿舍和实验室的编号以及学校的地图:地图上有N个路 口,M条路,经过每条路都需要一定的时间。 具体地说,就是要求无向图中,两对点间最短路的最长公共路径。
解析
这个题,怎么说呢,对我来说思维难度还是比较低的,但是代码难度稍微就高了点。
题目清楚的告诉我们要求两对点之间最短路的最大公共路径。实际上两点之间的最短路可能有多条,于是我们就要把它们都标出来。题目还提到希望在节约时间的前提下,一起走的时间尽可能的长,因此我们并不一定需要两人都只走各自的最短路,我们只需要让最终答案最优即可(即不能再更节约时间,一起走的时间不能再更长)。为了更好表示,我们引入一些符号。
设\(x1,y1\)之间所有最短路的边的集合为\(A\),\(x2,y2\)之间所有最短路的边的集合为\(B\)。我们首先要做的是找出这两个集合,然后比对\(A\)和\(B\),找出一个集合\(C\in A \cap B\),它就是两点对所有最短路径的公共边。
此时,我们只需要在\(C\)中找出一条最长的简单路径即可。为什么是简单路径呢,因为最短路本身就是简单路径嘛(废话)。
首先标记最短路上的边很容易,我们分别从起点终点两端点跑两遍最短路算法,然后再对每条边进行检查。假设起点为\(s\),终点为\(t\),对于某个点\(x\),它扩展出的点为\(y\),它们之间的边\(c(x,y)=z\),\(d[x]\)为到\(x\)点的最短路,如果有\(d[x]+d'[y]+z=d[t]\),那么这条边在\(s\rightarrow t\)最短路上。所以两对点我们要跑四次。注意,如果我们不跑两遍最短路的话,该方法会标记所有可达边。
所以接下来怎么找\(C\)中的最长简单路径呢?说实话我没想出来。
一开始打算在第二轮最短路时搞一个类似递推的东西统计。显然对于某个点\(y\),它可以由很多个点扩展而来,而我们只选取其中使得最长公共路径最大的一个点\(x\)扩展过来(当然首先这条边\(c(x,y)\)得在\(C\)中)。然而本人能力实在有限,并没有没码出来(就是菜)。看到题解里似乎也有人这么写,并且过了,我枯了。
遂看了题解,震惊,竟然可以用拓扑排序?!(我才不写什么狗屁重载呢,麻烦的很)
我还在纳闷无向图怎么搞拓扑的时候,人家已经想到分析两人同方向走和反方向走两种情况了!意思就是说我们可以考虑两人同方向和反方向走两种情况的最长公共路径,妙哉!
因此我们需要对两张图进行拓扑排序找最长链:\(x1\rightarrow y1\)所有最短路上的边按照\(x1\rightarrow y1\)的方向存,\(x2\rightarrow y2\)的所有最短路上的边按照\(x2\rightarrow y2\)的方向存的图1;\(x1\rightarrow y1\)所有最短路上的边按照\(x1\rightarrow y1\)的方向存,\(y2\rightarrow x2\)的所有最短路上的边按照\(y2\rightarrow x2\)的方向存的图2,注意这些最短路边包含在\(C\)中。
最后在两张图的最优解中择优。
神奇。
参考代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#define N 3010
using namespace std;
inline int read()
{
int f=1,x=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
struct rec{
int next,ver,edge;
}g[N*N],G[N*N];
int head[N],tot,headG[N],totG,n,m,x1,x2,y1,y2;
int d[4][N],ing[N],c[N];
bool v[N];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
inline void add(int x,int y,int val)
{
g[++tot].ver=y,g[tot].edge=val;
g[tot].next=head[x],head[x]=tot;
}
inline void addG(int x,int y,int val)
{
G[++totG].ver=y,G[totG].edge=val;
G[totG].next=headG[x],headG[x]=totG;
ing[y]++;
}
inline void dijkstra(int k,int x)
{
memset(d[k],0x3f,sizeof(d[k]));
memset(v,0,sizeof(v));
d[k][x]=0;q.push(make_pair(0,x));
while(q.size()){
int index=q.top().second;q.pop();
if(v[index]) continue;
v[index]=1;
for(int i=head[index];i;i=g[i].next){
int y=g[i].ver,z=g[i].edge;
if(d[k][y]>d[k][index]+z){
d[k][y]=d[k][index]+z;
q.push(make_pair(d[k][y],y));
}
}
}
}
inline void sign(int k)
{
for(int i=1;i<=n;++i)
for(int j=head[i];j;j=g[j].next){
int y=g[j].ver,z=g[j].edge;
if(d[0][i]+z+d[2][y]==d[0][y1]&&d[1][i]+z+d[3][y]==d[1][y2]&&k==1)
addG(i,y,z);
if(d[0][i]+z+d[2][y]==d[0][y1]&&d[3][i]+z+d[1][y]==d[1][y2]&&k==2)
addG(i,y,z);
}
}
int main()
{
n=read(),m=read();
x1=read(),y1=read(),x2=read(),y2=read();
for(int i=1;i<=m;++i){
int u,v,val;
u=read(),v=read(),val=read();
add(u,v,val),add(v,u,val);
}
dijkstra(0,x1),dijkstra(1,x2);
dijkstra(2,y1),dijkstra(3,y2);
//topsort
int ans=0;
queue<int> Q;
sign(1);
for(int i=1;i<=n;++i)
if(ing[i]==0) Q.push(i);
while(Q.size()){
int x=Q.front();Q.pop();
for(int i=headG[x];i;i=G[i].next){
int y=G[i].ver,z=G[i].edge;
if(--ing[y]==0){
c[y]=max(c[x]+z,c[y]);
ans=max(ans,c[y]);
Q.push(y);
}
}
}
memset(ing,0,sizeof(ing));
memset(headG,0,sizeof(headG));
memset(c,0,sizeof(c));
sign(2);
for(int i=1;i<=n;++i)
if(ing[i]==0) Q.push(i);
while(Q.size()){
int x=Q.front();Q.pop();
for(int i=headG[x];i;i=G[i].next){
int y=G[i].ver,z=G[i].edge;
if(--ing[y]==0){
c[y]=max(c[x]+z,c[y]);
ans=max(ans,c[y]);
Q.push(y);
}
}
}
cout<<ans<<endl;
return 0;
}
P2149 [SDOI2009]Elaxia的路线[最长公共路径]的更多相关文章
- 洛谷 P2149 [SDOI2009]Elaxia的路线 解题报告
P2149 [SDOI2009]Elaxia的路线 题目描述 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. Elaxia ...
- 洛谷——P2149 [SDOI2009]Elaxia的路线
P2149 [SDOI2009]Elaxia的路线 题目描述 最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间.Elaxia和w每 ...
- Luogu P2149 [SDOI2009]Elaxia的路线(最短路+记忆化搜索)
P2149 [SDOI2009]Elaxia的路线 题意 题目描述 最近,\(Elaxia\)和\(w**\)的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们必须合理地安排两个人在一起的 ...
- P2149 [SDOI2009]Elaxia的路线
题目描述 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. Elaxia和w**每天都要奔波于宿舍和实验室之间,他们 希望在 ...
- 洛谷 P2149 [SDOI2009]Elaxia的路线
题目描述 最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间.Elaxia和w每天都要奔波于宿舍和实验室之间,他们 希望在节约时间的 ...
- 洛谷—— P2149 [SDOI2009]Elaxia的路线
https://www.luogu.org/problem/show?pid=2149 题目描述 最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两 ...
- Luogu P2149 [SDOI2009]Elaxia的路线 | 图论
题目链接 题解: 题面中给了最简洁清晰的题目描述:"求无向图中,两对点间最短路的最长公共路径". 对于这个问题我们可以先考虑图中的哪些边对这两对点的最短路产生了贡献. 比如说下面这 ...
- bzoj1880: [Sdoi2009]Elaxia的路线(spfa,拓扑排序最长路)
1880: [Sdoi2009]Elaxia的路线 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 1944 Solved: 759[Submit][St ...
- Spfa+DP【p2149】[SDOI2009]Elaxia的路线
Description 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. Elaxia和w**每天都要奔波于宿舍和实验室之间 ...
随机推荐
- mysql类型转换函数convert与cast的用法
原文地址:https://blog.csdn.net/kouwoo/article/details/45535733 简单介绍下mysql数据库中用于类型转换的二个函数,convert与cast函数, ...
- LeetCode 611. 有效三角形的个数(Valid Triangle Number)
611. 有效三角形的个数 611. Valid Triangle Number 题目描述 LeetCode LeetCode LeetCode611. Valid Triangle Number中等 ...
- 【面试】C++类中的相关函数【构造,拷贝构造,析构,友元】
构造函数:值的初始化,可带参数,无返回值,可重载,可存在多个 析构函数:释放对象内存空间,无参数,无返回值,不可重载,只能存在一个 拷贝构造函数:拷贝对象,其形参必须是引用 1.空类会默认添加哪些东西 ...
- python-tkinter使用方法——转载(一)
Tkinter图形界面设计(GUI) 转载URL:https://www.cnblogs.com/pywjh/p/9527828.html#lable [因为这是我第一个接触的GUI图形界面py ...
- Wing-AEP平台LWM2M设备接入
实现Wing-AEP中国电信物联网开放平台,LWM2M设备接入 一.准备 接入模组:BC35-G 平台地址:https://www.ctwing.cn/ 点击右上角控制台 点击左侧栏点击产品中心 二. ...
- Linux(ubuntu)软件的安装
通过apt安装/卸载软件 apt是advanced packaging tool,是Linxu下的一款安装包管理程序 可以在终端中方便的安装/卸载/更新软件包 # 安装软件 sudo apt inst ...
- Golang_互斥锁
为什么需要锁? 在并发的情况下,多个线程或协程同时去修改一个变量.使用锁能保证在某一时间点内,只有一个协程或线程修改这一变量. 锁的概念就是,我正在处理 a(锁定),你们等着,等我处理完了(解锁),你 ...
- grafana部署安装
部署grafana 在prometheus& grafana server节点部署grafana服务. 1. 下载&安装 # 下载 [root@prometheus ~]# cd /u ...
- CF1097G Vladislav and a Great Legend 组合、树形背包
传送门 看到\(k\)次幂求和先用斯特林数拆幂:\(x^k = \sum\limits_{i=1}^k \binom{x}{i}\left\{ \begin{array}{cccc} k \\ i \ ...
- Dubbo学习摘录(二)
扩展点机制 扩展点的配置 (1)根据关键字读取配置,获取具体的实现类 比如在 dubbo-demo-provider.xml 文件中配置: 则会根据rmi去读取具体的协议实现类RmiProtocol. ...