code vs 搭桥

1002 搭桥

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 黄金 Gold
题解
 查看运行结果
题目描述 Description

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

code vs 搭桥_第1张图片
输入描述 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

数据范围及提示 Data Size & Hint

见描述



#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int map[100][100],f[100][100],flag[100][100];
int n,m,i,j,num,k;
int xl[10]={0,-1,0,1,-1,-1,1,1},yl[10]={-1,0,1,0,-1,1,-1,1};
int x[10000],y[10000],a,dis;
int father[10000000],bridge;
struct data 
{
int x,y,len;
};data road[10000000];
int find(int x1)//用并查集把属于同一个建筑的合并到一起
{
if (father[x1]==x1)
return x1;
father[x1]=find(father[x1]);
return father[x1];
}
void dfs(int x1,int y1)//搜索一共有多少个建筑物
{
for (int i=0;i<=7;i++)
{
int xx=x1+xl[i]; int yy=y1+yl[i];
if (xx<=n&&xx>=1&&yy<=m&&yy>=1&&f[xx][yy]==1)
{
f[xx][yy]=0;
int r1=find(flag[x1][y1]);
int r2=find(flag[xx][yy]);
father[r2]=r1;
dfs(xx,yy);
}
}
}
void chuli()//处理路径,因为路径只能沿着矩形的边,所以如果可以连边,那么横纵坐标至少有一个差值不超过1
{
for (int l=1;l<=k-1;l++)
for (int h=l+1;h<=k;h++)
 {
  if (abs(x[l]-x[h])<=1)
  {
  a++;
  road[a].x=l;
  road[a].y=h;
  road[a].len=abs(y[l]-y[h])-1;
  }
  if (abs(y[l]-y[h])<=1)
  {
  a++;
  road[a].x=l;
  road[a].y=h;
  road[a].len=abs(x[l]-x[h])-1;
  }
 }
}
int cmp(data a,data b)
{
return a.len<b.len;
}
int main()
{
scanf("%d%d\n",&n,&m);
for (i=1;i<=n*m;i++)
father[i]=i;
for (i=1;i<=n;i++)
{
char s[100];
gets(s);
for (j=1;j<=m;j++)
if (s[j-1]=='.')
 f[i][j]=map[i][j]=0;
else
 {
   f[i][j]=map[i][j]=1; 
   k++; x[k]=i; y[k]=j; flag[i][j]=k;
 }
}
for (i=1;i<=n;i++)
for (j=1;j<=m;j++)
 if (f[i][j]==1)
 {
  f[i][j]=0;
  dfs(i,j);
  num++;
 }
chuli();
for (i=1;i<=k;i++)
int r1=find(father[i]);
sort(road+1,road+a+1,cmp);
for (i=1;i<=a;i++)//最小生成树
{
int r1=find(road[i].x);
int r2=find(road[i].y);
if (r1!=r2)
{
dis+=road[i].len;
bridge++;
father[r2]=r1;
}
if (bridge==num-1)
{
break;
}
}
printf("%d\n",num);
printf("%d %d",bridge,dis);
return 0;
}


你可能感兴趣的:(code vs 搭桥)