/* Sat Mar 20 22:38:09 JST 2004 */ /* Sun Mar 21 00:13:28 JST 2004 */ #include #include #include typedef struct { int v1, v2, len; } edge_t; edge_t edges[1024]; int n_edges; int r, c; int field[52][52]; int n_building; int adj[256][256]; void Kruskal(int *n_bridges, int *bridge_length) { int i, j, mixed; int group[256]; *n_bridges = *bridge_length = 0; for (i = 1; i <= n_building; i++) { group[i] = i; } for (i = 0; i < n_edges; i++) { if (group[edges[i].v1] == group[edges[i].v2]) { continue; } mixed = group[edges[i].v2]; for (j = 1; j <= n_building; j++) { if (group[j] == mixed) { group[j] = group[edges[i].v1]; } } (*n_bridges)++; (*bridge_length) += edges[i].len; } } int edgecmp(const void *_x, const void *_y) { edge_t *x = (edge_t *)_x, *y = (edge_t *)_y; if (x->len < y->len) { return -1; } if (x->len > y->len) { return +1; } return 0; } void extract(int sy, int sx, int dy, int dx, int *length, int *target) { int i; for (i = 1; ; i++) { if (sy+dy*i <= 0 || sy+dy*i >= r+1 || sx+dx*i <= 0 || sx+dx*i >= c+1) { *target = 0; break; } if (field[sy+dy*i][sx+dx*i] > 0) { if (field[sy+dy*i][sx+dx*i] == field[sy][sx]) { *target = 0; return; } *length = i - 1; *target = field[sy+dy*i][sx+dx*i]; return; } } *target = 0; } void fill(int y, int x, int n) { int i, j, k, flag, ii, jj; int dx[8] = {1, 1, 1, 0, -1, -1, -1, 0}; int dy[8] = {-1, 0, 1, 1, 1, 0, -1, -1}; field[y][x] = n; while (1) { flag = 0; for (i = 1; i <= r; i++) { for (j = 1; j <= c; j++) { if (field[i][j] == n) { for (k = 0; k < 8; k++) { if (field[i+dy[k]][j+dx[k]] < 0) { field[i+dy[k]][j+dx[k]] = n; flag = 1; } } } } } if (!flag) { break; } } } int main() { int icase; int i, j, len; char s[1024]; int n_bridges, bridge_length; for (icase = 1; ; icase++) { gets(s); sscanf(s, "%d%d", &r, &c); if (r == 0 && c == 0) { break; } for (i = 0; i <= r+1; i++) { for (j = 0; j <= c+1; j++) { field[i][j] = c; } } for (i = 1; i <= r; i++) { gets(s); len = strlen(s); for (j = 1; j <= len; j++) { if (s[j-1] == '#') { field[i][j] = -1; } if (s[j-1] == '.') { field[i][j] = 0; } } } n_building = 1; for (i = 1; i <= r; i++) { for (j = 1; j <= c; j++) { if (field[i][j] < 0) { fill(i, j, n_building); n_building++; } } } n_building--; for (i = 0; i <= n_building; i++) { for (j = 0; j <= n_building; j++) { adj[i][j] = INT_MAX; } } for (i = 1; i <= r; i++) { for (j = 1; j <= c; j++) { int length, target; if (field[i][j] == 0) { continue; } extract(i , j - 1, -1, 0, &length, &target); if (target && adj[field[i][j]][target] > length) { adj[field[i][j]][target] = adj[target][field[i][j]] = length; } extract(i , j , -1, 0, &length, &target); if (target && adj[field[i][j]][target] > length) { adj[field[i][j]][target] = adj[target][field[i][j]] = length; } extract(i - 1, j , 0, 1, &length, &target); if (target && adj[field[i][j]][target] > length) { adj[field[i][j]][target] = adj[target][field[i][j]] = length; } extract(i , j , 0, 1, &length, &target); if (target && adj[field[i][j]][target] > length) { adj[field[i][j]][target] = adj[target][field[i][j]] = length; } extract(i , j - 1, 1, 0, &length, &target); if (target && adj[field[i][j]][target] > length) { adj[field[i][j]][target] = adj[target][field[i][j]] = length; } extract(i , j , 1, 0, &length, &target); if (target && adj[field[i][j]][target] > length) { adj[field[i][j]][target] = adj[target][field[i][j]] = length; } extract(i - 1, j , 0, -1, &length, &target); if (target && adj[field[i][j]][target] > length) { adj[field[i][j]][target] = adj[target][field[i][j]] = length; } extract(i , j , 0, -1, &length, &target); if (target && adj[field[i][j]][target] > length) { adj[field[i][j]][target] = adj[target][field[i][j]] = length; } } } n_edges = 0; for (i = 1; i <= n_building; i++) { for (j = i+1; j <= n_building; j++) { if (adj[i][j] > 0 && adj[i][j] != INT_MAX) { edges[n_edges].v1 = i; edges[n_edges].v2 = j; edges[n_edges].len = adj[i][j]; n_edges++; } } } qsort(edges, n_edges, sizeof(edge_t), edgecmp); Kruskal(&n_bridges, &bridge_length); if (icase > 1) { printf("\n"); } printf("City %d\n", icase); if (n_building <= 1) { printf("No bridges are needed.\n"); continue; } if (n_bridges == 0) { printf("No bridges are possible.\n"); } else if (n_bridges == 1) { printf("1 bridge of total length %d\n", bridge_length); } else { printf("%d bridges of total length %d\n", n_bridges, bridge_length); } if (n_building-1 > n_bridges) { printf("%d disconnected groups\n", n_building - n_bridges); } } return 0; }