如果两人的有向路径交既有同向边,也有反向边。因为最短路径是链,所以必定有人走的不是最短路。
并且在满足都是同向或者都是反向的前提下,有向路径交只要在两人的最短路径有向无环图上,就一定是合法的。因为有向路径交如果不能被一条链覆盖,就说明必须多绕路,同样与最短路径不符。
先选一个人搞出它起点到终点的最短路径有向无环图,然后另一个人再拓扑排序,同向和反向各算一遍取 (max) 即可。
注意拓扑排序考虑入度时不在最短路径有向无环图中的点不能算在内,这个可以一遍 DFS 处理出来。
code:
#include<bits/stdc++.h>
using namespace std;
#define N 1505
#define Max(x,y)((x)>(y)?x:y)
#define For(i,x,y)for(i=x;i<=(y);i++)
struct node
{
int next,to,w,type;
}e[2250005];
bool bo[N];
queue<int>que;
int head[N],dis[N],deg[N],len[N],g=1,n,mx;
inline void add(int u,int v,int w)
{
e[++g].w=w;
e[g].to=v;
e[g].next=head[u];
head[u]=g;
}
void SPFA(int s)
{
int i,u,v;
For(i,1,n)dis[i]=INT_MAX>>1;
que.push(s);
dis[s]=0;
while(!que.empty())
{
u=que.front();
bo[u]=0;
for(i=head[u];i;i=e[i].next)
{
v=e[i].to;
if(dis[v]>dis[u]+e[i].w)
{
dis[v]=dis[u]+e[i].w;
if(!bo[v])que.push(v),bo[v]=1;
}
}
que.pop();
}
}
void dfs1(int u)
{
if(bo[u])return;
int i,v;
bo[u]=1;
for(i=head[u];i;i=e[i].next)
{
v=e[i].to;
if(dis[u]==dis[v]+e[i].w)
{
e[i].type=2;
e[i^1].type=1;
dfs1(v);
}
}
}
void dfs2(int u,int rem)
{
int i,v;
mx=Max(mx,len[u]);
for(i=head[u];i;i=e[i].next)
{
v=e[i].to;
if(dis[u]==dis[v]+e[i].w)
{
/*printf("%d %d %d
",u,v,deg[v]);*/
deg[v]--;
len[v]=Max(len[v],len[u]+(e[i].type==rem)*e[i].w);
if(!deg[v])dfs2(v,rem);
}
}
}
void dfs3(int u)
{
if(bo[u])return;
int i,v;
bo[u]=1;
for(i=head[u];i;i=e[i].next)
{
v=e[i].to;
if(dis[u]==dis[v]+e[i].w)dfs3(v);
}
}
int main()
{
int m,x,xx,y,yy,u,v,w,i;
scanf("%d%d%d%d%d%d",&n,&m,&x,&y,&xx,&yy);
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w),add(v,u,w);
}
SPFA(x);
dfs1(y);
For(i,1,n)bo[i]=0;
SPFA(xx);
For(i,1,n)bo[i]=0;
dfs3(yy);
For(u,1,n)
for(i=head[u];i;i=e[i].next)
if(bo[e[i].to])deg[u]+=dis[e[i].to]-e[i].w==dis[u];
dfs2(yy,1);
For(u,1,n)
{
len[u]=deg[u]=0;
for(i=head[u];i;i=e[i].next)
if(bo[e[i].to])deg[u]+=dis[e[i].to]-e[i].w==dis[u];
}
dfs2(yy,2);
printf("%d",mx);
return 0;
}