题意:有n条村落连接线路,给你m个草儿附近的村落,在给出t个草儿想去的地方。从草儿附近的村落出发到她想去的地方所有线路中的花费时间最少的一个。
解析:(一)、多源多点最短路,暴力枚举
(二)、相对第一种提高了效率,即将附近村落直接存入至mapp[ 0 ][ tmp ] //tmp为附近村落数;同理,将想要到达的地方存至mapp[ nn ][ tmp ];
这么做,相当于固定起点为0点,而从0点出发寻找最短距离。相反,终点则为单一终点发散多个重点,因此原图需要扩展横纵一个单元。因此最大边长需要加一。由于起点之前下标由1出发,所有,直接将起点存至0点即可。
第一种方法:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 1005;
const int Max = 0xfffffff;
int mapp[ maxn ][ maxn ], start[ maxn ], end[ maxn ], dis[ maxn ], vis[ maxn ];
int n, m, t, a, b, ti, nn;
void Dijkstra( int start ){
memset( vis, 0, sizeof( vis ) );
vis[ start ] = 1;
for( int i = 1; i <= nn; ++i ){
dis[ i ] = mapp[ start ][ i ];
}
/* for( int i = 1; i <= nn; ++i ){
cout << dis[ i ] << endl;
}
cout << endl << endl;*/
dis[ start ] = 0;
for( int i = 1; i <= nn; ++i ){
int temp = Max, k;
for( int j = 1;j <= nn; ++j ){
if( !vis[ j ] && temp > dis[ j ] ){
temp = dis[ k = j ];
}
}
vis[ k ] = 1;
if( temp == Max )
break;
for( int j = 1; j <= nn; ++j ){
if( !vis[ j ] && dis[ j ] > dis[ k ] + mapp[ k ][ j ] ){
dis[ j ] = dis[ k ] + mapp[ k ][ j ];
}
}
}
}
int main(){
while( scanf( "%d%d%d", &n, &m, &t ) != EOF ){
for( int i = 0; i <= maxn; ++i ){
dis[ maxn ] = Max;
for( int j = 0; j <= maxn; ++j ){
mapp[ i ][ j ] = Max;
}
}
nn = -1;
for( int i = 1; i <= n; ++i ){
scanf( "%d%d%d", &a, &b, &ti );
if( mapp[ a ][ b ] > ti ){
mapp[ a ][ b ] = mapp[ b ][ a ] = ti;
}
if( a > nn ){
nn = a;
}
if( b > nn ){
nn = b;
}
}
for( int i = 1; i <= m; ++i ){
scanf( "%d", &start[ i ] );
}
for( int i = 1; i <= t; ++i ){
scanf( "%d", &end[ i ] );
}
int ans = Max;
for( int i = 1; i <= m; ++i ){
Dijkstra( start[ i ] );
for( int j = 1; j <= t; ++j ){
if( ans > dis[ end[ j ] ] )
ans = dis[ end[ j ] ];
// cout << dis[ end[ j ] ] << endl;
}
}
printf( "%d\n", ans );
}
return 0;
}
第二种方法
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 1005;
const int Max = 0xfffffff;
int mapp[ maxn ][ maxn ], start[ maxn ], end[ maxn ], dis[ maxn ], vis[ maxn ];
int n, m, t, a, b, ti, nn, tmp;
int Dijkstra( ){
memset( vis, 0, sizeof( vis ) );
vis[ 0 ] = 1;
for( int i = 1; i <= nn; ++i ){
dis[ i ] = mapp[ 0 ][ i ];
}
dis[ 0 ] = 0;
for( int i = 0; i <= nn; ++i ){
int temp = Max, k;
for( int j = 0;j <= nn; ++j ){
if( !vis[ j ] && temp > dis[ j ] ){
temp = dis[ k = j ];
}
}
vis[ k ] = 1;
if( temp == Max )
break;
for( int j = 0; j <= nn; ++j ){
if( !vis[ j ] && dis[ j ] > dis[ k ] + mapp[ k ][ j ] ){
dis[ j ] = dis[ k ] + mapp[ k ][ j ];
}
}
}
return dis[ nn ];
}
int main(){
while( scanf( "%d%d%d", &n, &m, &t ) != EOF ){
for( int i = 0; i <= maxn; ++i ){
dis[ maxn ] = Max;
for( int j = 0; j <= maxn; ++j ){
mapp[ i ][ j ] = Max;
}
}
nn = -1;
for( int i = 1; i <= n; ++i ){
scanf( "%d%d%d", &a, &b, &ti );
if( mapp[ a ][ b ] > ti ){
mapp[ a ][ b ] = mapp[ b ][ a ] = ti;
}
if( a > nn ){
nn = a;
}
if( b > nn ){
nn = b;
}
}
nn++;
for( int i = 1; i <= m; ++i ){
scanf( "%d", &tmp );
mapp[ tmp ][ 0 ] = mapp[ 0 ][ tmp ] = 0;
}
for( int i = 1; i <= t; ++i ){
scanf( "%d", &tmp );
mapp[ nn ][ tmp ] = mapp[ tmp ][ nn ]= 0;
}
printf( "%d\n", Dijkstra( ) );
}
return 0;
}