求 s 1 − > t 1 s1->t1 s1−>t1的最短路和 s 2 − > t 2 s2->t2 s2−>t2的最多相同节点
肯定从点 t 1 , t 2 t1,t2 t1,t2开始跑最短路
这样从 s 1 , s 2 s1,s2 s1,s2出发只能走最短路上的边
而且如果定义 f [ i ] [ j ] f[i][j] f[i][j]为第一条路在 i i i,第二条路在 j j j时,还能相同的最多点数
显然终止条件 f [ t 1 ] [ t 2 ] f[t1][t2] f[t1][t2]为 0 0 0
而且因为只能走最短路边,所以是一个 D A G DAG DAG图
这样记忆化搜索就不许需要担心卡死
爆搜即可
#include <bits/stdc++.h>
using namespace std;
const int N = 309;
const int inf = 2e9+1;
struct edge{
int to,nxt,w;
}d[N*N*2]; int head[N*N*2],cnt=1;
void add(int u,int v,int w)
{
d[++cnt].to=v,d[cnt].nxt = head[u],d[cnt].w=w,head[u] = cnt;
}
int dis1[N],dis2[N],n,m,vis[N];
typedef pair<int,int>p;
void dijstra(int s,int dis[])
{
for(int i=1;i<=300;i++) dis[i] = inf, vis[i] = 0;
priority_queue<p,vector<p>,greater<p> >q; q.push( p(0,s) );
dis[s] = 0;
while( !q.empty() )
{
int u = q.top().second; q.pop();
if( vis[u] ) continue;
vis[u] = 1;
for(int i=head[u];i;i=d[i].nxt )
{
int v = d[i].to;
if( dis[v]>dis[u]+d[i].w )
{
dis[v] = dis[u]+d[i].w;
q.push( p(dis[v],v) );
}
}
}
}
int f[N][N],s1,s2,t1,t2;
int dfs(int u1,int u2)
{
if( u1==t1&&u2==t2 ) return 0;
if( f[u1][u2]!=-1 ) return f[u1][u2];
for(int i=head[u1];i;i=d[i].nxt )//u1先走
{
int v = d[i].to;
if( dis1[v]!=dis1[u1]-d[i].w ) continue;
f[u1][u2] = max( f[u1][u2],dfs(v,u2)+(v==u2) );
}
for(int i=head[u2];i;i=d[i].nxt )
{
int v = d[i].to;
if( dis2[v]!=dis2[u2]-d[i].w ) continue;
f[u1][u2] = max( f[u1][u2],dfs(u1,v)+(v==u1) );
}
return f[u1][u2];
}
int main()
{
while( cin >> n >> m && (n+m) )
{
for(int i=1;i<=m;i++)
{
int l,r,w; scanf("%d%d%d",&l,&r,&w);
if( l==r ) continue;
add(l,r,w); add(r,l,w);
}
cin >> s1 >> t1 >> s2 >> t2;
dijstra(t1,dis1); dijstra(t2,dis2);
memset( f,-1,sizeof f );
cout << dfs(s1,s2)+(s1==s2) << '\n';
cnt = 1;
for(int i=1;i<=300;i++) head[i] = 0;
}
}