题目链接:https://vjudge.net/problem/POJ-3026
题意:题目讲的其实有点迷糊。。。总的来说就是,在一个地图上,你需要把所有的‘A’和‘S’连接起来,使得所有线段累加长度最短,那么很显然,这里需要最小生成树。
思路:地图上分布着‘A’和‘S’,我们需要把图上的信息提取出一个图,G(V,E)。那么我们就可以用prime算法了。
开始,我们可以先把‘A’和‘S’编号,然后用bfs跑地图,枚举每个‘A’和‘S’其他的‘A’和‘S’的距离,先生成一个距离矩阵,生成了矩阵之后,就可以套prime板子了。
建图是关键,代码中会有些解释
1 #include <iostream> 2 #include <cstring> 3 #include<vector> 4 #include<string> 5 #include <cmath> 6 #include <map> 7 #include <queue> 8 #include <algorithm> 9 #include <cstdio> 10 using namespace std; 11 12 #define inf 99999 13 #define rep(i,j,k) for(int i = (j); i <= (k); i++) 14 #define rep__(i,j,k) for(int i = (j); i < (k); i++) 15 #define per(i,j,k) for(int i = (j); i >= (k); i--) 16 #define per__(i,j,k) for(int i = (j); i > (k); i--) 17 18 19 const int N = 110; 20 int mv_x[] = {0,0,1,-1}; 21 int mv_y[] = {1,-1,0,0}; 22 int G[N][N]; //路线 23 string mp[N]; //原始地图 24 int num[N][N];//编号图 25 bool vis[N][N];//bfs 26 int sx,sy;//S 27 int n,m; 28 int cnt;//编号 29 30 struct node{ 31 32 int x,y,v; 33 }; 34 35 36 void init_G(){ 37 38 rep(i,1,cnt){ 39 rep(j,1,cnt){ 40 if(i == j) G[i][j] = 0; 41 else G[i][j] = inf; 42 } 43 } 44 } 45 46 void set_num(){ 47 48 cnt = 0; 49 rep__(i,0,n){ 50 rep__(j,0,m){ 51 if(mp[i][j] == 'A' || mp[i][j] == 'S') num[i][j] = ++cnt; //把‘A’和‘S’编号 52 } 53 } 54 } 55 56 inline bool check(int x,int y){ 57 return x >= 0 && x < n && y >= 0 && y < m; 58 } 59 60 void bfs(int now_x,int now_y){ 61 62 memset(vis,0,sizeof(vis)); 63 64 int po = num[now_x][now_y]; //该点的编号 65 66 queue<node > que; 67 que.push(node{now_x,now_y,0}); 68 vis[now_x][now_y] = true; 69 70 while(!que.empty()){ 71 72 node tmp = que.front(); 73 que.pop(); 74 75 //遇到了其他的点,得到一条边 76 if(mp[tmp.x][tmp.y] == 'A' || mp[tmp.x][tmp.y] == 'S'){ 77 G[po][num[tmp.x][tmp.y]] = min(G[po][num[tmp.x][tmp.y]],tmp.v); 78 } 79 80 rep__(p,0,4){ 81 82 int dx = tmp.x + mv_x[p]; 83 int dy = tmp.y + mv_y[p]; 84 85 if(check(dx,dy) && mp[dx][dy] != '#' && !vis[dx][dy]){ 86 87 vis[dx][dy] = true; 88 89 que.push(node{dx,dy,tmp.v + 1}); 90 } 91 } 92 } 93 94 } 95 96 void work(){ 97 98 rep__(i,0,n){ 99 rep__(j,0,m){ 100 if(mp[i][j] == 'A' || mp[i][j] == 'S'){ 101 bfs(i,j); //每个点跑bfs 102 } 103 } 104 } 105 } 106 107 //prime板子 108 int prime(){ 109 110 bool VIS[N]; 111 int dis[N]; 112 memset(VIS, 0, sizeof(VIS)); 113 114 rep(i,1,cnt) dis[i] = G[1][i]; 115 116 VIS[1] = true; 117 118 rep(i,2,cnt){ 119 120 int x = i; 121 int vv = inf; 122 123 rep(j,1,cnt){ 124 if(!VIS[j] && vv > dis[j]) vv = dis[x = j]; 125 } 126 127 if(x == -1) continue; 128 129 VIS[x] = 1; 130 131 rep(j,1,cnt){ 132 if(!VIS[j] && dis[j] > G[x][j]) 133 dis[j] = G[x][j]; 134 } 135 } 136 137 int sum = 0; 138 rep(i,1,cnt) sum += dis[i]; 139 140 return sum; 141 } 142 143 144 int main(){ 145 146 147 int T; 148 scanf("%d",&T); 149 150 while(T--){ 151 152 scanf("%d%d\n",&m,&n); 153 154 rep__(i,0,n) gets(mp[i]); 155 156 set_num();//设置编号 157 init_G(); //初始化G 158 work(); 159 160 161 // rep(i,1,cnt){ 162 // rep(j,1,cnt) printf("%d",G[i][j]); 163 // printf("\n"); 164 // } 165 166 // printf("ans\n"); 167 printf("%d\n",prime()); 168 169 } 170 171 172 getchar();getchar(); 173 return 0; 174 }