一个人的旅行

点击打开链接

题意:有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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值