http://poj.org/problem?id=3026
题意:给你一个迷宫,里面有 ‘S’起点,‘A’标记,‘#’墙壁,‘ ’空地。求从S出发,经过所有A所需要的最短路。你有一个特殊能力,当走到S或A时可以分身出任意多个人一起走。计算路程时就是所有人的总路程之和。
题解:想一下,是裸的最短路套上bfs。
先暴力bfs出各个点之间的距离,存边
然后kruskal
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<queue> #include<algorithm> #include<iostream> #include<vector> #include<string.h> #include<set> #include<string> using namespace std; const int maxn = 3e4;; int len1, len2, p[maxn], ans; set<int> s; struct edge { int to, from, w; edge(int to=0, int from=0, int w=0) :to(to), from(from), w(w) {} }; vector<edge> e; bool cmp(edge a, edge b) { return a.w < b.w; } int f[maxn]; int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); } void un(int x, int y) { int u = find(x), v= find(y); f[u] = v; } bool same(int x, int y) { return find(x) == find(y); } string map[55]; int id[55][55]; int vis[55][55]; int dir[4][2] = { 0,1 ,1,0, 0,-1, -1,0 }; struct node { int x, y, t; node(int x=0, int y=0, int t = 0) :x(x), y(y), t(t) {} }; void bfs(int x, int y) { memset(vis, 0, sizeof(vis)); queue<node> Q; Q.push(node(x, y, 0)); vis[x][y] = 1; while (!Q.empty()) { node now = Q.front(); Q.pop(); for (int i = 0; i < 4; i++) { int dx = now.x + dir[i][0]; int dy = now.y + dir[i][1]; if (map[dx][dy] == '#'||vis[dx][dy]) continue; if (map[dx][dy] == 'A')e.push_back(edge(id[x][y], id[dx][dy], now.t+1)); Q.push(node(dx, dy, now.t + 1)); vis[dx][dy] = 1; } } } int main() { int t; cin >> t; while (t--) { int n, m; scanf("%d %d ", &n,&m); for (int i = 0; i < m; i++) { getline(cin, map[i]); } memset(id, 0, sizeof(id)); e.clear(); int idx = 1; for(int i=0;i<m;i++) for (int j = 0; j < n; j++) { if (map[i][j] == 'S')map[i][j] = 'A'; if (map[i][j] == 'A' ) { id[i][j] = idx++; } } for (int i = 0; i<m; i++) for (int j = 0; j < n; j++) { if(id[i][j])bfs(i, j); } for (int i = 1; i < idx; i++) { f[i] = i; } sort(e.begin(), e.end(),cmp); int res = 0; for (int i = 0; i < e.size(); i++) { if (same(e[i].to, e[i].from)) continue; un(e[i].to, e[i].from); res += e[i].w; } cout << res << endl; } system("pause"); }