题目描述:
求两个起终点的最短路的最长公共路径
题目分析:
我们跑4遍SPFA,分别求出四个点到所有点的最短路.
枚举每条边 然后判断这条边是否都满足两者的最短路
最后做一下拓扑求一下最长路径即可
题目链接:
Ac 代码:
// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
const int maxm=1e6+100;
int dis[4][maxm];
int head[maxm],to[maxm<<1],net[maxm<<1],cost[maxm<<1],cnt;
bool vis[maxm];
int du[maxm],ans[maxm];
std::queue <int> dl;
int n,m;
int s1,t1,s2,t2;
inline void addedge(int u,int v,int c)
{
cnt++;
to[cnt]=v,cost[cnt]=c,net[cnt]=head[u],head[u]=cnt;
}
int ahead[maxm],ato[maxm<<1],anet[maxm<<1],acost[maxm<<1],acnt;
inline void Addedge(int u,int v,int c)
{
acnt++;
du[v]++;
ato[acnt]=v,acost[acnt]=c,anet[acnt]=ahead[u],ahead[u]=acnt;
}
inline void SPFA(int s,int t)
{
dis[t][s]=0;
vis[s]=1;
dl.push(s);
while(!dl.empty())
{
int now=dl.front();
dl.pop();
vis[now]=0;
for(int i=head[now];i;i=net[i])
if(dis[t][to[i]]>dis[t][now]+cost[i])
{
dis[t][to[i]]=dis[t][now]+cost[i];
if(!vis[to[i]]) vis[to[i]]=1,dl.push(to[i]);
}
}
}
struct node{
int u,v,cost;
}d[maxm];
void topsort()
{
int res=0;
for(int i=1;i<=n;i++)
if(!du[i]) dl.push(i);
while(!dl.empty())
{
int now=dl.front();
dl.pop();
for(int i=ahead[now];i;i=anet[i])
{
int tmp=ato[i];
ans[tmp]=std::max(ans[tmp],ans[now]+acost[i]);
res=std::max(res,ans[tmp]);
du[tmp]--;
if(!du[tmp]) dl.push(tmp);
}
}
printf("%d\n",res);
}
int main()
{
memset(dis,127/3,sizeof(dis));
scanf("%d%d",&n,&m);
scanf("%d%d%d%d",&s1,&t1,&s2,&t2);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&d[i].u,&d[i].v,&d[i].cost);
addedge(d[i].u,d[i].v,d[i].cost);
addedge(d[i].v,d[i].u,d[i].cost);
}
SPFA(s1,0),SPFA(t1,1),SPFA(s2,2),SPFA(t2,3);
for(int i=1;i<=m;i++)
{
int u=d[i].u,v=d[i].v,c=d[i].cost;
int c1=std::min(dis[0][u],dis[0][v])+std::min(dis[1][u],dis[1][v])+c;
int c2=std::min(dis[2][u],dis[2][v])+std::min(dis[3][u],dis[3][v])+c;
if(c1==dis[0][t1]&&c2==dis[2][t2])
dis[0][u]<dis[0][v]?Addedge(u,v,c):Addedge(v,u,c);
}
topsort();
return 0;
}