这题显然还是用prim,经过优化后的prim效率可以达到O(n2)。 离省赛越来越近,我也越来越没有状态,这种小白题从昨天晚上开始做,做到断网;今天爬起来继续做,才发现是把a[i][k]赋值 无限大的条件写错了——无良的出题者居然加入了两个端点间距离可能为0的情况...... #include <cstdio>#include <string> int a[1010][1010], s[1010], dis[1010], t, n; void pd (){ int i; for ( i = 0; i < n; i ++ ) { printf ( "%d ", dis[i] ); } printf ( "\n" );} void init (){ int i, k; scanf ( "%d", &n ); for ( i = 0; i < n; i ++ ) { scanf ( "%d", &s[i] ); } for ( i = 0; i < n; i ++ ) { for ( k = 0; k < n; k ++ ) { scanf ( "%d", &a[i][k] ); if ( i == k ) { a[i][k] = 9999; } else { a[i][k] += s[i] + s[k]; } } } memset ( dis, 0, sizeof ( dis ) );} void prim (){ int i, k, sum = 0; dis[0] = -1; for ( i = 1; i < n; i ++ ) { dis[i] = a[0][i]; } for ( i = 1; i < n; i ++ ) { //pd (); int mx = 9999, j; for ( k = 0; k < n; k ++ ) { if ( dis[k] != -1 && dis[k] < mx ) { j = k; mx = dis[k]; } } sum += mx; dis[j] = -1; for ( k = 0; k < n; k ++ ) { if ( a[j][k] < dis[k] ) { dis[k] = a[j][k]; } } } printf ( "%d\n", sum );} int main (){ //freopen ( "in.txt", "r", stdin ); scanf ( "%d", &t ); int i; for ( i = 0; i < t; i ++ ) { init (); prim (); } return 0;}

评论