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**每天都要奔波于宿舍和实验室之间 ...
随机推荐
- 【计算机视觉】PASCAL VOC数据集分析
PASCAL VOC数据集分析 PASCAL VOC为图像识别和分类提供了一整套标准化的优秀的数据集,从2005年到2012年每年都会举行一场图像识别challenge. 本文主要分析PASCAL V ...
- 在ObjectARX中创建OPM项目的时候出现 MIDL1012: argument illegal for switch / header错误的解决方式
修改为 这样新建的带有MIDL项目就不会提示错误这个错误了. 如果你已经建立好项目,可以尝试修改MIDL的配置,头文件可能是.h没有文件名,所以出现MIDL1012错误,修改为项目名称的.h即可,保持 ...
- 最新 北森java校招面经 (含整理过的面试题大全)
从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.北森等10家互联网公司的校招Offer,因为某些自身原因最终选择了北森.6.7月主要是做系统复习.项目复盘.LeetCode ...
- LeetCode 686. 重复叠加字符串匹配(Repeated String Match)
686. 重复叠加字符串匹配 686. Repeated String Match 题目描述 给定两个字符串 A 和 B,寻找重复叠加字符串 A 的最小次数,使得字符串 B 成为叠加后的字符串 A 的 ...
- 16.Python略有小成(内置模块Ⅱ)
Python(内置模块Ⅱ) 一.规范化开发 一个py文件中 文件加载问题 代码可读性,查询差 要将一个py文件分开,合理的分成多个py文件 配置文件放在一起 : 一些轻易不改变的变量,一般命名 set ...
- 什么是openshift
Openshift是一个开源的容器云平台,底层基于当前容器的事实标准编排系统Kubernetes和docker引擎,企业可以基于此平台搭建内部Paas平台,贯穿CI/CD流程,提高企业IT效率,拥抱D ...
- golang - 映射 ini 配置文件
使用:setting.AppSetting.PageSize 包:go get github.com/go-ini/ini
- 启迪链网通证经济共同体:柏链教育&火聘online推出区块链行业人才“一门式”服务
近日,启迪链网通证经济共同体旗下两个节点成员柏链教育与火聘online,达成节点间的合作,据悉本次合作是采用共同体的生态共建模式,柏链教育与火聘online共享企业端岗位需求的大数据,然后有针对性的开 ...
- [LOJ3086] [GXOI2019] 逼死强迫症
题目链接 LOJ:https://loj.ac/problem/3086 洛谷:https://www.luogu.org/problemnew/show/P5303 Solution 显然不考虑\( ...
- UOJ46 清华集训2014玄学(线段树)
注意到操作有结合律,容易想到用一个矩形表示第i次操作对第j个位置的数的影响.那么修改是单行内的区间修改,而查询是单列内的区间查询.这样二维线段树上以列为外层行为内层直接打标记就可以维护.然后就喜闻乐见 ...