http://acm.hust.edu.cn/vjudge/contest/121380#problem/I
题意:求有字母的各个点都彼此连接起来的最短步数。
分析:一看到题就想到BFS+最小生成树了, 可是我一开始不知道怎么表示,也没看穿题(还是渣渣啊。。)
**************************************************************************************************************************************
根据题意的“分离”规则,重复走过的路不再计算
因此当使用prim算法求L的长度时,根据算法的特征恰好不用考虑这个问题(源点合并很好地解决了这个问题),L就是最少生成树的总权值W
由于使用prim算法求在最小生成树,因此无论哪个点做起点都是一样的,(通常选取第一个点),因此起点不是S也没有关系
所以所有的A和S都可以一视同仁,看成一模一样的顶点就可以了
#include<algorithm> #include<stdio.h> #include<string.h> #include<queue> using namespace std; const int maxn = 105; const int oo = 0xfffffff; int dir[4][2] = { {1,0},{0,1},{-1,0},{0,-1} }; char maps[maxn][maxn]; int v[maxn][maxn], dist[maxn], a[maxn][maxn], p[maxn][maxn], vis[maxn]; int n, m; struct node { int x, y, step; }; void BFS(int u, int x, int y) { memset(v, 0, sizeof(v)); node begins, now, next; begins.x = x; begins.y = y; begins.step = 0; queue<node>Q; Q.push(begins); v[x][y] = 1; while(Q.size()) { now = Q.front(); Q.pop(); if(maps[now.x][now.y]>='A' && maps[now.x][now.y] <='Z') p[u][a[now.x][now.y]] = now.step; for(int i=0; i<4; i++) { next.x = now.x + dir[i][0]; next.y = now.y + dir[i][1]; if(next.x>0 && next.x<=m && next.y>0 && next.y<=n && maps[next.x][next.y]!='#' && !v[next.x][next.y]) { v[next.x][next.y] = 1; next.step = now.step + 1; Q.push(next); } } } } void Prim(int k) { memset(vis, 0, sizeof(vis)); int sum = 0; for(int i=1; i<=k; i++) dist[i] = p[1][i]; vis[1] = 1; for(int i=1; i<k; i++) { int index = -1; int mins = oo; for(int j=1; j<=k; j++) { if(!vis[j] && dist[j]<mins) { mins = dist[j]; index = j; } } sum += mins; vis[index] = 1; for(int j=1; j<=k; j++) { if(!vis[j] && dist[j] > p[index][j]) dist[j] = p[index][j]; } } printf("%d ", sum); } int main() { int T; scanf("%d", &T); while(T --) { int k = 1; scanf("%d %d ", &n, &m); for(int i=1; i<=m; i++) { gets(maps[i]); for(int j=1; j<=n; j++) { if(maps[i][j]=='A' || maps[i][j]=='S') a[i][j] = k++; } } for(int i=1; i<=m; i++) { for(int j=1; j<=n; j++) if(i == j) p[i][j] = 0; else p[i][j] = oo; } for(int i=1; i<=m; i++) { for(int j=1; j<=n; j++) { if(maps[i][j]>='A' && maps[i][j] <='Z') BFS(a[i][j], i, j); } } Prim(k-1); } return 0; }