一个大陆上有K个城市,其中有N个城市属于国家A,M个城市属于国家B。给出导弹在任意两个城市间的飞行时间,问若国家A的每个城市都部署了一枚导弹,求国家A摧毁国家B最少需要多少时间。
第一届新手赛预选赛的最后一题,属于图论问题,综合了多种算法,貌似只有一个测试样例,时间要求并不苛刻。首先,用佛洛依德算法求出任意两个城市间最短的导弹飞行时间(导弹居然会转弯……),再用二分趋近的方法,对每一个可能的时间,用匈牙利算法判断二分图(国家A和国家B)的最大匹配是否是完全匹配,进而求出最小时间。
另:佛洛依德算法比较容易理解,关键在于寻求中间节点C使得从A到C再到B的时间比从A到B的时间少(当然C不一定存在)。C点依次选取所有的节点,核心思路是二二归一达到最简,方法简单易行但耗时较大。而匈牙利算法的关键在于寻求增广路径,以此来不断扩充(就是将增广路径上的每条边都取反,匹配数就多了一个)原来的匹配图,直到最大匹配,个中还涉及了深度优先检索的算法。
Run Time: 0.04sec
Run Memory: 348KB
Code length: 2077Bytes
SubmitTime: 2011-12-16 12:08:32
// Problem#: 1794
// Submission#: 1090043
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <cstdio>
#include <cstring>
using namespace std;
int K, N, M;
int time[ 101 ][ 101 ];
int A[ 101 ], B[ 101 ];
int attack[ 101 ], defend[ 101 ];
bool included[ 101 ];
bool find( int n, int min );
bool match( int min );
int main()
{
int i, j, k;
int bot, top, mid;
while ( scanf( "%d", &K ) && K ) {
for ( i = 1; i <= K; i++ ) {
for ( j = 1; j <= K; j++ )
scanf( "%d", &time[ i ][ j ] );
}
for ( k = 1; k <= K; k++ ) {
for ( i = 1; i <= K; i++ ) {
for ( j = 1; j <= K; j++ ) {
if ( time[ i ][ k ] + time[ k ][ j ] < time[ i ][ j ] )
time[ i ][ j ] = time[ i ][ k ] + time[ k ][ j ];
}
}
}
scanf( "%d", &N );
for ( i = 1; i <= N; i++ )
scanf( "%d", &A[ i ] );
scanf( "%d", &M );
for ( i = 1; i <= M; i++ )
scanf( "%d", &B[ i ] );
bot = 1;
top = 100;
while ( bot < top ) {
mid = ( bot + top ) / 2;
match( mid ) ? top = mid - 1: bot = mid + 1;
}
printf( "%d\n", match( top ) ? top: top + 1 );
}
return 0;
}
bool find( int n, int min ) {
for ( int i = 1; i <= N; i++ ) {
if ( time[ A[ i ] ][ n ] <= min && !included[ A[ i ] ] ) {
included[ A[ i ] ] = true;
if ( attack[ A[ i ] ] == 0 || find( attack[ A[ i ] ], min ) ) {
defend[ n ] = A[ i ];
attack[ A[ i ] ] = n;
return true;
}
}
}
return false;
}
bool match( int min ) {
memset( attack, 0, sizeof( attack ) );
memset( defend, 0, sizeof( defend ) );
for ( int i = 1; i <= M; i++ ) {
if ( defend[ B[ i ] ] == 0 ) {
memset( included, false, sizeof( included ) );
if ( !find( B[ i ], min ) )
return false;
}
}
return true;
}
本文探讨了一种在复杂图论背景下,通过应用佛洛依德算法和匈牙利算法解决国家间导弹防御策略的问题。具体而言,文章通过实例展示了如何计算任意两个城市间的最短导弹飞行时间,并利用二分趋近法和匈牙利算法找出最优的导弹部署方案,以最小化国家A摧毁国家B所需的时间。
818

被折叠的 条评论
为什么被折叠?



