P2149 [SDOI2009]Elaxia的路线(最短路)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2149 [SDOI2009]Elaxia的路线(最短路)相关的知识,希望对你有一定的参考价值。

P2149 [SDOI2009]Elaxia的路线(最短路)

题意

求两对最短路的最长公共路径。

思路

结论是两对最短路的最长公共路径是一条链。

考虑跑 4 4 4次最短路求出每对起点和终点的最短路。

然后判断一条边是否在最短路上出现就可以:

d 1 [ u ] + w + d 2 [ v ] = d 1 [ e d ] d_1[u]+w+d_2[v]=d_1[ed] d1[u]+w+d2[v]=d1[ed]

d 1 d_1 d1是对于 s t st st的最短路, d 2 d_2 d2是对于 e d ed ed的最短路。

我们把一条边同时在 ( s t , e d ) , ( s t 1 , e d 1 ) (st,ed),(st_1,ed_1) (st,ed),(st1,ed1) 加入到新图,注意相遇也是算公共,所以要特判下反边是否也满足,然后进行重新建图。

我们建的是个有向图,所以可以跑 d p dp dp​,记忆化搜索求出 d p u dp_u dpu u u u出发的最长路径。

时间复杂度: O ( m l o g n ) O(mlogn) O(mlogn)

// Problem: P2149 [SDOI2009]Elaxia的路线
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2149
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Date: 2021-08-17 10:00:40
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1505,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define ios ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 
}
int n,m;
struct edge{
	int to,nt,w;
}e[M<<1],e1[M<<1];
int h[N],h1[N],cnt,cnt1;
void add(int u,int v,int w){
	e[++cnt]={v,h[u],w},h[u]=cnt;
	e[++cnt]={u,h[v],w},h[v]=cnt;
}
bitset<N>bj;
void add1(int u,int v,int w){
	e1[++cnt1]={v,h1[u],w},h1[u]=cnt1,bj[u]=bj[v]=1;
}
int d1[N],d2[N],d3[N],d4[N];
bitset<N>vis;
void dij(int st,int *d){
	priority_queue<PII>q;
	vis.reset();
	memset(d,0x3f,sizeof d1);
	d[st]=0,q.push({0,st});
	while(!q.empty()){
		int u=q.top().se;q.pop();
		if(vis[u]) continue;vis[u]=1;
		for(int i=h[u];i;i=e[i].nt){
			int v=e[i].to,w=e[i].w;
			if(!vis[v]&&d[v]>d[u]+w){
				d[v]=d[u]+w;
				q.push({-d[v],v});
			}
		}
	}
}
int s1,t1,s2,t2;
int dp[N],ans;
int dfs(int u){
	if(dp[u]) return dp[u];
	for(int i=h1[u];i;i=e1[i].nt){
		int v=e1[i].to,w=e1[i].w;
		dp[u]=max(dp[u],dfs(v)+w);
	}
	ans=max(ans,dp[u]);
	return dp[u];
}
int main(){
	scanf("%d%d",&n,&m);
	scanf("%d%d%d%d",&s1,&t1,&s2,&t2);
	for(int i=1,u,v,w;i<=m;i++){
		scanf("%d%d%d",&u,&v,&w);add(u,v,w);
	}
	dij(s1,d1),dij(t1,d2),dij(s2,d3),dij(t2,d4);
	for(int u=1;u<=n;u++)
		for(int i=h[u];i;i=e[i].nt){
			int v=e[i].to,w=e[i].w;
			if(d1[u]+w+d2[v]==d1[t1]){
				if(d3[u]+w+d4[v]==d3[t2]) add1(u,v,w);
				if(d3[v]+w+d4[u]==d3[t2]) add1(v,u,w);
			}
		}
	for(int i=1;i<=n;i++) if(bj[i]&&!dp[i]) dfs(i);
	printf("%d\\n",ans);
	return 0;
}

以上是关于P2149 [SDOI2009]Elaxia的路线(最短路)的主要内容,如果未能解决你的问题,请参考以下文章

P2149 [SDOI2009]Elaxia的路线

P2149 [SDOI2009]Elaxia的路线

洛谷—— P2149 [SDOI2009]Elaxia的路线

P2149 [SDOI2009]Elaxia的路线

P2149 [SDOI2009]Elaxia的路线[最长公共路径]

P2149 [SDOI2009]Elaxia的路线