http://poj.org/problem?id=3026
题意:任意两个字母可以连线,求把所有字母串联起来和最小。
很明显这就是一个最小生成树,不过这个题有毒。他的输入有问题。在输入m和N后面,可能有一大串的空格。就因为这个,我RE都有点懵了,要不是discuss里面有人说输入有问题,我都没注意到这个,原本只用了一个getchar吃掉最后的换行符。没想到之后还有空格。有点小坑。
思路:这个题目如果他给你一个图,那就是最裸的prim了。不过这个题的难点也就是在他给的图你不能用Prim,你只能通过bfs去建立一个你可以新图,让这个新图去使用最小生成树。
1 #include <string.h> 2 #include <stdio.h> 3 #include <queue> 4 #define inf 0x3f3f3f 5 #define maxn 300 6 7 using namespace std; 8 9 char mgraph[ maxn ][ maxn ]; 10 int bfsgraph[ maxn ][ maxn ],dist[ maxn ][ maxn ],num[ maxn ][ maxn ],ans,dis[ maxn ]; 11 bool mark[ maxn ][ maxn ],vis[ maxn ]; 12 13 14 struct note{ 15 int x,y; 16 }; 17 18 void bfs(int x,int y) //我是把图建在bfsgraph里面的。 19 { 20 memset( dist , 0 ,sizeof( dist ) ); 21 memset( mark , true , sizeof( mark ) ); 22 bfsgraph[ num[ x ][ y ] ][ num[ x ][ y ] ] = 0; 23 queue<note >s; 24 note p,q; 25 p.x = x; 26 p.y = y; 27 dist[ x ][ y ] = 0; 28 mark[ x ][ y ] = false; 29 s.push(p); 30 while(!s.empty()) 31 { 32 p = s.front(); 33 s.pop(); 34 if(mark[ p.x + 1 ][ p.y ] && mgraph[ p.x + 1 ][ p.y ] != '#') 35 { 36 if( num[ p.x + 1 ][ p.y ]) bfsgraph[ num[ x ][ y ] ][ num[ p.x+1 ][ p.y ]] = dist[ p.x ][ p.y ] + 1; //如果当前点为字母的话,那么把这个点与起始点的距离给记录。 37 dist[ p.x + 1 ][ p.y ] = dist[ p.x ][ p.y ] + 1; 38 mark[ p.x + 1 ][ p.y ] = false; 39 q.x = p.x + 1; 40 q.y = p.y; 41 s.push(q); 42 } 43 if(mark[ p.x ][ p.y - 1 ] && mgraph[ p.x ][ p.y - 1 ] != '#') 44 { 45 if( num[ p.x ][ p.y - 1 ]) bfsgraph[ num[ x ][ y ] ][ num[ p.x ][ p.y - 1 ]] = dist[ p.x ][ p.y ] + 1; 46 dist[ p.x ][ p.y - 1 ] = dist[ p.x ][ p.y ] + 1; 47 mark[ p.x ][ p.y - 1 ] = false; 48 q.x = p.x; 49 q.y = p.y - 1; 50 s.push(q); 51 } 52 if(mark[ p.x ][ p.y + 1 ] && mgraph[ p.x ][ p.y + 1 ] != '#') 53 { 54 if( num[ p.x ][ p.y + 1 ]) bfsgraph[ num[ x ][ y ] ][ num[ p.x ][ p.y + 1 ]] = dist[ p.x ][ p.y ] + 1; 55 56 57 dist[ p.x ][ p.y + 1 ] = dist[ p.x ][ p.y ] + 1; 58 mark[ p.x ][ p.y + 1 ] = false; 59 q.x = p.x; 60 q.y = p.y + 1; 61 s.push(q); 62 } 63 if(mark[ p.x - 1 ][ p.y ] && mgraph[ p.x - 1 ][ p.y ] != '#') 64 { 65 if( num[ p.x-1 ][ p.y ]) bfsgraph[ num[ x ][ y ] ][ num[ p.x - 1 ][ p.y ]] = dist[ p.x ][ p.y ] + 1; 66 dist[ p.x - 1 ][ p.y ] = dist[ p.x ][ p.y ] + 1; 67 mark[ p.x - 1 ][ p.y ] = false; 68 q.x = p.x - 1; 69 q.y = p.y; 70 s.push(q); 71 } 72 } 73 } 74 int prim(int pos) 75 { 76 for(int i = 1; i < pos ; i++) 77 dis[ i ] = inf ; dis[ 1 ] = 0; 78 for(int i = 1;i < pos ; i++){ 79 int tep = inf;int k = 0; 80 for(int j = 1 ; j < pos ; j++){ 81 if(vis[ j ]&&dis[ j ]<tep) 82 { 83 tep = dis[ j ]; 84 k = j; 85 } 86 } 87 if(tep == inf) return 0; 88 ans += tep; 89 vis[ k ]=false; 90 for(int j = 1 ;j < pos ; j++) 91 if(vis[ j ]&&dis[ j ] > bfsgraph[ k ][ j ]) 92 dis[ j ] = bfsgraph[ k ][ j ]; 93 } 94 return 0; 95 } 96 97 98 99 int main() 100 { 101 // freopen("in.txt","r",stdin); 102 int t,m,n; 103 char s[50]; 104 scanf("%d",&t); 105 while( t-- ) 106 { 107 memset( mgraph , 0 , sizeof( mgraph ) ); 108 memset( bfsgraph , 0 , sizeof( bfsgraph ) ); 109 memset( num , 0 , sizeof( num ) ); 110 scanf("%d%d",&m,&n); 111 gets(s); //这里要注意,要吃掉m,n后面的空格,不然就等着RE吧。 112 ans = 0; 113 int pos = 1; 114 note point[ 150 ]; 115 for( int i = 0 ; i < n ; i++ ) 116 gets(mgraph[i]); 117 for( int i = 0 ; i < n ; i++ ) 118 for( int j = 0 ; j < m ; j++ ) 119 if( mgraph [ i ][ j ] == 'A' || mgraph[ i ][ j ] == 'S') 120 { 121 point[ pos ].x = i; 122 point[ pos ].y = j; 123 num[ i ][ j ] = pos; //我用num来编号,相当于一个映射,一个点集与一个数集之间的映射,因为要建图。 124 pos ++; 125 } 126 for( int i = 1 ; i < pos ; i++ ) //对每一个点进行bfs。 127 bfs( point[ i ].x , point[ i ].y ); 128 memset( vis , true , sizeof( vis ) ); 129 prim(pos); 130 printf("%d ",ans); 131 } 132 return 0; 133 }