codevs1002搭桥 bfs+最小生成树

题目描述 Description

有一矩形区域的城市中建筑了若干建筑物,如果某两个单元格有一个点相联系,则它们属于同一座建筑物。现在想在这些建筑物之间搭建一些桥梁,其中桥梁只能沿着矩形的方格的边沿搭建,如下图城市1有5栋建筑物,可以搭建4座桥将建筑物联系起来。城市2有两座建筑物,但不能搭建桥梁将它们连接。城市3只有一座建筑物,城市4有3座建筑物,可以搭建一座桥梁联系两栋建筑物,但不能与第三座建筑物联系在一起。

输入描述 Input Description

在输入的数据中的第一行包含描述城市的两个整数r 和c, 分别代表从北到南、从东到西的城市大小(1 <= r <= 50 and 1 <= c <= 50). 接下来的r 行, 每一行由c 个(“#”)和(“.”)组成的字符. 每一个字符表示一个单元格。“#”表示建筑物,“.”表示空地。

输出描述 Output Description

在输出的数据中有两行,第一行表示建筑物的数目。第二行输出桥的数目和所有桥的总长度。

样例输入 Sample Input

样例1

3 5
#…#
..#..
#…#

样例2

3 5
##…
…..
….#

样例3

3 5
#.###
#.#.#
###.#

样例4:

3 5
#.#..
…..
….#

样例输出 Sample Output

样例1

5
4 4

样例2

2
0 0

样例3

1
0 0

样例4

3
1 1

题解:

关于题意,一定要注意所修的桥是只能沿着直线的,并且不限长度,一开始,在这里就让坑了。。。
对于第一问,我们只需要bfs一遍就求出来了,但是第二问真的很麻烦
因为要求最短边长和最少边数,那么就可以建边后跑最小生成树,用并查集来维护两个块是否联通。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int r, c, qsum = 0, qlen = 0, ans = 0, tot = 0;
int map[100][100];
char lsm[100][100];
int xx[5] = {0, 0, 0, 1, -1};
int yy[5] = {0, 1, -1, 0, 0};
int fa[23333];
struct qer
{
    int x, y;
};
struct edge
{
    int from, to, cost;
}es[233333];
queue <qer> q;
void build(int f, int t, int d)
{
    es[++tot] = (edge){f, t, d};
}
int find(int x)
{
    return fa[x] == x ? x : fa[x] = find(fa[x]);
}
bool cmp(edge a, edge b)
{
    return a.cost < b.cost;
}
void bfs(int x, int y)
{
    while (!q.empty())
        q.pop();
    q.push((qer){x, y});
    map[x][y] = ans;
    while (!q.empty())
    {
        qer a = q.front();
        q.pop();
        for (int i = 1; i <= 4; i++)
        for (int j = 1; j <= 4; j++)
        {
            int lx = a.x + xx[i];
            int ly = a.y + yy[j];
            if (!xx[i]&&!yy[j])
                continue;
            if (lx < 1 || lx > r || ly < 1 || ly > c || map[lx][ly] != -1)
                continue;
            q.push((qer){lx, ly});
            map[lx][ly] = ans;
        }
    }
}
void deal()
{
    sort(es+1, es+tot+1, cmp);
    for (int i = 1; i <= tot; i++)
    {
        int x = es[i].from, y = es[i].to;
        if (find(x) != find(y))
        {
            fa[find(x)] = find(y);
            qlen += es[i].cost;
            // cout << es[i].from << " ceshi " << es[i].to << endl;
            qsum++;
        }
    }
}
void work(int x, int y)
{
    bool l = 0, r = 0;
    for (int i = 2; x + i <= r; i++)
    {
        int lx = x + i;
        if (y+1 <= c && map[lx][y+1] && map[lx][y+1] != map[x][y] && !l)
            build (map[lx][y+1], map[x][y], i-1), l = 1;
        if (y-1 >= 1 && map[lx][y-1] && map[lx][y-1] != map[x][y] && !r)
            build (map[lx][y-1], map[x][y], i-1), r = 1;
        if (map[lx][y] && map[lx][y] != map[x][y] && (!r || !l))
        {
            build (map[lx][y], map[x][y], i-1), r = 1, l = 1;
            break;
        }
    }
    l = 0, r = 0;
    for (int i = 2; x - i >= 1; i++)
    {
        int lx = x - i;
        if (y+1 <= c && map[lx][y+1] && map[lx][y+1] != map[x][y] && !l)
            build (map[lx][y+1], map[x][y], i-1), l = 1;
        if (y-1 >= 1 && map[lx][y-1] && map[lx][y-1] != map[x][y] && !r)
            build (map[lx][y-1], map[x][y], i-1), r = 1;
        if (map[lx][y] && map[lx][y] != map[x][y] && (!r || !l))
        {
            build (map[lx][y], map[x][y], i-1), r = 1, l = 1;
            break;
        }
    }
    l = 0, r = 0;
    for (int i = 2; y + i <= c; i++)
    {
        int ly = y + i;
        if (x+1 <= r && map[x+1][ly] && map[x+1][ly] != map[x][y] && !l)
            build (map[x+1][ly], map[x][y], i-1), l = 1;
        if (x-1 >= 1 && map[x-1][ly] && map[x-1][ly] != map[x][y] && !r)
            build (map[x-1][ly], map[x][y], i-1), r = 1;
        if (map[x][ly] && map[x][ly] != map[x][y] && (!r || !l))
        {
            build (map[x][ly], map[x][y], i-1), r = 1, l = 1;
            break;
        }
    }
    l = 0, r = 0;
    for (int i = 2; y - i >= 1; i++)
    {
        int ly = y - i;
        if (x+1 <= r && map[x+1][ly] && map[x+1][ly] != map[x][y] && !l)
            build (map[x+1][ly], map[x][y], i-1), l = 1;
        if (x-1 >= 1 && map[x-1][ly] && map[x-1][ly] != map[x][y] && !r)
            build (map[x-1][ly], map[x][y], i-1), r = 1;
        if (map[x][ly] && map[x][ly] != map[x][y] && (!r || !l))
        {
            build (map[x][ly], map[x][y], i-1), r = 1, l = 1;
            break;
        }
    }
}
void ceshi()
{
    puts("");
    for (int i = 1; i <= r; i++)
    {
        for (int j = 1; j <= c; j++)
        {
            cout << map[i][j] << " ";
        }
        puts("");
    }
    for (int i = 1; i <= tot; i++)
        cout << es[i].from << " " << es[i].to << " " << es[i].cost << endl;
}
int main()
{
    for (int i = 1; i <= 20000; i++)
        fa[i] = i;
    cin >> r >> c;
    char a;
    for (int i = 1; i <= r; i++)
    for (int j = 1; j <= c; j++)
        cin >> lsm[i][j];
    for (int i = 1; i <= r; i++)
    for (int j = 1; j <= c; j++)
    {
        if (lsm[i][j] == '#')
            map[i][j] = -1;
        else
            map[i][j] = 0;
    }
    for (int i = 1; i <= r; i++)
    for (int j = 1; j <= c; j++)
    {
        if (map[i][j] == -1)
            ans++, bfs(i, j);
    }
    cout << ans << endl;
    for (int i = 1; i <= r; i++)
    for (int j = 1; j <= c; j++)
    {
        if (map[i][j])
        {
            work(i, j);
        }
    }
    deal();
    cout << qsum << " " << qlen;
    // ceshi();
    return 0;
}
/*
4 5
#.#.#
.###.
..#..
#.#.#
36 11
#.....##...
#.......##.
#.......#.#
#...#....#.
##.#...#..#
....####...
..#...#.##.
..........#
.##.#......
.#..#..#..#
#.####.#...
#..##.#....
.#..#.....#
#......####
...#.......
...#......#
#........#.
..#.#.#..##
......##.#.
...##....#.
#.#.....#..
##.#......#
##..#.#.#.#
.###.##....
........###
.##.#...#..
#.#.#.#....
...#.#..#..
....#..#.##
...#.#..#..
......####.
#.......##.
..##......#
#...###..#.
.......#...
....##.....
*/

 

上一篇
下一篇