题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2833
求两个人的起点和终点的最短路径上最多能有多少个相同点。
用Floyd求出任意两点之间的最短路。
假设做完Floyd的数组为A,则有如下性质。A[a][b]==A[a][i]+A[i][j]+A[j][b];如我们在做Floyd时同时计算出任意两点之间的最短路上经过的点的个数。则在作完Floyd之后,枚举前面公式中的i和j。就能得出结果。
至于为什么公共点一定会组成顺序一样的相同路径,可用反证法证明。
#include <iostream>
#include <stdio.h>
#include <memory.h>
using namespace std;
#define INF 10000000
int A[305][305],B[305][305];
int N,M;
void Floyd()
{
for(int k=1;k<=N;k++)
{
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
{
if(A[i][j]>A[i][k]+A[k][j])
{
A[i][j]=A[i][k]+A[k][j];
B[i][j]=B[i][k]+B[k][j];
}
else if(A[i][j]==A[i][k]+A[k][j]&&B[i][j]<B[i][k]+B[k][j])
{
B[i][j]=B[i][k]+B[k][j];
}
}
}
}
}
void Init()
{
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
{
A[i][j]=INF;
}
A[i][i]=0;
}
memset(B,0,sizeof(B));
}
int main()
{
int a,b,c,d;
int s,e,w;
while(scanf("%d%d",&N,&M))
{
if(N==0&&M==0)
break;
Init();
while(M--)
{
scanf("%d%d%d",&s,&e,&w);
if(A[s][e]<w)
continue;
A[s][e]=w;
A[e][s]=w;
B[s][e]=1;//保存的是不算终点的情况下,所经历的个数。若要保存算上终点时的个数,则在Floyd中的B数组更新时要减去1,不然会多计算一边k点。
B[e][s]=1;
}
scanf("%d%d%d%d",&a,&b,&c,&d);
Floyd();
int ans=-1;//必须初始化为-1,否则在没有公共点时,本应该输出0,却会输出1.
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
{
if((A[a][b]==A[a][i]+A[i][j]+A[j][b])
&&(A[c][d]==A[c][i]+A[i][j]+A[j][d])
&&(ans<B[i][j]))
ans=B[i][j];
}
}
cout<<ans+1<<endl;//要加上公共路径中的终点,所以要加1.
}
return 0;
}
原文:http://www.cnblogs.com/modengdubai/p/4743499.html