传送门:【HDU】2833 WuKong
题目分析:首先floyd预处理出任意两点间的最短路,在求最短路的时候如果两条最短路一样长则取节点数较多的那条。
由于最短路的性质,如果两条不同的最短路要有公共路径,则这条公共路径一定是由连续的点构成,否则一定存在一条更短的最短路。
求完最短路后我们得到了数组cnt[ i ][ j ]表示从i到j的最短路上的最多的节点数。
如果cnt[ s ][ t ] = cnt[ s ][ i ] + cnt[ i ][ j ] + cnt[ j ][ t ] - 2,则说明路径i->j在s->t的最短路上。
现在我们枚举所有的cnt[ i ][ j ]来找到最长的即在最短路s1->t1,又在最短路s2->t2上的公共路径。
ans = max { cnt[ i ][ j ] | 1 <= i <= n , 1 <= j <= n , cnt[ s1 ][ t1 ] = cnt[ s1 ][ i ] + cnt[ i ][ j ] + cnt[ j ][ t1 ] - 2 , cnt[ s2 ][ t2 ] = cnt[ s2 ][ i ] + cnt[ i ][ j ] + cnt[ j ][ t2 ] - 2 }。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define REP( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i )
#define FOR( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
#define REV( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )
const int MAXN = 305 ;
const int MAXH = 2005 ;
const int MAXE = 2005 ;
const int INF = 0x3f3f3f3f ;
int n , m , q ;
int s1 , t1 , s2 , t2 ;
int G[MAXN][MAXN] ;
int cnt[MAXN][MAXN] ;
void scanf ( int& x , char c = 0 ) {
while ( ( c = getchar () ) < '0' || c > '9' ) ;
x = c - '0' ;
while ( ( c = getchar () ) >= '0' && c <= '9' ) x = x * 10 + c - '0' ;
}
void solve () {
int u , v , c ;
CLR ( G , INF ) ;
CLR ( cnt , 0 ) ;
FOR ( i , 1 , n ) G[i][i] = 0 , cnt[i][i] = 1 ;
while ( m -- ) {
scanf ( u ) , scanf ( v ) , scanf ( c ) ;
if ( G[u][v] > c ) {
G[u][v] = G[v][u] = c ;
cnt[u][v] = cnt[v][u] = 2 ;
}
}
scanf ( s1 ) , scanf ( t1 ) , scanf ( s2 ) , scanf ( t2 ) ;
FOR ( k , 1 , n ) FOR ( i , 1 , n ) FOR ( j , 1 , n ) {
int tmp = G[i][k] + G[k][j] ;
if ( G[i][j] > tmp ) {
G[i][j] = tmp ;
cnt[i][j] = cnt[i][k] + cnt[k][j] - 1 ;
} else if ( G[i][j] == tmp && cnt[i][j] < cnt[i][k] + cnt[k][j] - 1 )
cnt[i][j] = cnt[i][k] + cnt[k][j] - 1 ;
}
int ans = 0 ;
FOR ( i , 1 , n ) FOR ( j , 1 , n ) if ( ans < cnt[i][j] )
if ( cnt[s1][t1] == cnt[s1][i] + cnt[i][j] + cnt[j][t1] - 2 )
if ( cnt[s2][t2] == cnt[s2][i] + cnt[i][j] + cnt[j][t2] - 2 )
ans = cnt[i][j] ;
printf ( "%d\n" , ans ) ;
}
int main () {
while ( ~scanf ( "%d%d" , &n , &m ) && ( n || m ) ) solve () ;
return 0 ;
}