codevs 1002 搭桥

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codevs 1002 搭桥相关的知识,希望对你有一定的参考价值。

题目描述 Description

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

技术分享
输入描述 Input Description

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

 

输出描述 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

 

分析:

dfs+krustal。

先搜索出每栋不同的楼,并且计算楼与楼之间的间隔。

再利用最小生成树算法将其可联通边联通即可。

#include<iostream>
#include<algorithm>
using namespace std;
char a[60][60];
int book[60][60];
int fx[3601];
int n,m;
int dx[9]={0,0,0,1,-1,1,1,-1,-1},dy[9]={0,1,-1,0,0,1,-1,1,-1};
int cnt=0,cnt_b=0;
struct node{
    int s,f,w;
}t[3601];
bool cmp(const node &a,const node &b)
{
    return a.w<b.w;
}
void dfs(int x,int y)
{
    book[x][y]=cnt;
    for(int i=1;i<=8;++i)
    {
        int tx=x+dx[i],ty=y+dy[i];
        if(a[tx][ty]==#)
        {
            a[tx][ty]=.;
            dfs(tx,ty);
        }
    }
}
void find(int x,int y)
{
    for(int i=1;i<=m;++i)
    {
        if(y+i>m)break;
        if(book[x][y+1]==book[x][y])break;
        for(int j=1;j<=8;++j)
        {
            int tx=x+dx[j],ty=y+i+dy[j];
            if(book[tx][ty]!=0&&book[tx][ty]!=book[x][y])
            {
                ++cnt_b;
                t[cnt_b].s=book[x][y];
                t[cnt_b].f=book[tx][ty];
                t[cnt_b].w=i;
            }
        }
    }
    for(int i=1;i<=n;++i)
    {
        if(x+i>n)break;
        if(book[x+1][y]==book[x][y])break;
        for(int j=1;j<=8;++j)
        {
            int tx=x+i+dx[j],ty=y+dy[j];
            if(book[tx][ty]!=0&&book[tx][ty]!=book[x][y])
            {
                ++cnt_b;
                t[cnt_b].s=book[x][y];
                t[cnt_b].f=book[tx][ty];
                t[cnt_b].w=i;
            }
        }
    }
}
int find(int n)
{
    if(fx[n]==n)return n;
    else return fx[n]=find(fx[n]);
}
bool merge(int s,int f)
{
    int a=find(s),b=find(f);
    if(a!=b)
    {
        fx[b]=a;
        return 1;
    }
    else return 0;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n*m;++i)fx[i]=i;
    for(int i=1;i<=n;++i)
    for(int j=1;j<=m;++j)cin>>a[i][j];
    for(int i=1;i<=n;++i)
    {
        for(int j=1;j<=m;++j)
        {
            if(a[i][j]==#)
            {
                a[i][j]=.;
                ++cnt;
                dfs(i,j);
            }
        }
    }
/*    for(int i=1;i<=n;++i)
    {
        for(int j=1;j<=m;++j)
        {
            cout<<book[i][j]<<" "; 
        }
        cout<<endl;
    }
*/
    for(int i=1;i<=n;++i)
    {
        for(int j=1;j<=m;++j)
        {
            if(book[i][j]!=0)find(i,j);
        }
    }
//    for(int i=1;i<=cnt_b;++i)cout<<t[i].s<<" "<<t[i].f<<" "<<t[i].w<<endl;
    sort(t+1,t+cnt_b+1,cmp);
    int k=0,sum=0;
    for(int i=1;i<=cnt_b;++i)
    {
        if(merge(t[i].s,t[i].f))
        {
            ++k;
            sum+=t[i].w;
        }
    }
    cout<<cnt<<endl;
    cout<<k<<" "<<sum;
    return 0;
}

 

以上是关于codevs 1002 搭桥的主要内容,如果未能解决你的问题,请参考以下文章

CodeVS 1002-搭桥

codevs 1002 搭桥

codevs 1002 搭桥

搭桥(最小生成树)

并查集DFS搭桥

Code VS 1002 搭桥