题目链接: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; }
时间: 2024-11-03 03:33:20