您的位置:首页 > 其它

【codevs1002】搭桥

2016-01-03 19:10 169 查看
题目描述 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

【题解】

dfs+kruskal 不要妄想读懂我的代码

【代码】

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int sx[8]={1,1,1,0,0,-1,-1,-1};
int sy[8]={1,0,-1,1,-1,1,0,-1};
int n,m,tot,num,u,v,p,q,side,sum,sidesum;
char s[100];
int a[100][100],f[2505][2505],fa[3000];
struct hp{
int x,y,z;
}b[1000000];
bool pd;
inline void dfs(int s,int t){
for (int i=0;i<8;++i){
int x=s+sx[i],y=t+sy[i];
if (x>0&&x<=n&&y>0&&y<=m&&a[x][y]==-1){
a[x][y]=tot;
dfs(x,y);
}
}
}
int cmp(hp a,hp b){
return a.z<b.z;
}
int find(int x){
if (x==fa[x]) return x;
fa[x]=find(fa[x]);
return fa[x];
}
int merge(int x,int y){
int f1=find(x);
int f2=find(y);
fa[f1]=f2;
}
int main(){
scanf("%d%d\n",&n,&m);
for (int i=1;i<=n;++i){
gets(s);
for (int j=1;j<=m;++j)
if (s[j-1]=='#') a[i][j]=-1;
}
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
if (a[i][j]==-1){
tot++; a[i][j]=tot;
dfs(i,j);
}
printf("%d\n",tot);
if (tot==1){
printf("0 0\n"); return 0;
}
/*	for (int i=1;i<=n;++i){
for (int j=1;j<=m;++j)
printf("%d",a[i][j]);
printf("\n");
}*/
memset(f,127/3,sizeof(f));
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
for (int k=1;k<=n;++k)
for (int l=1;l<=m;++l){
u=abs(i-k); v=abs(j-l);
if (a[i][j]!=0&&a[k][l]!=0&&a[i][j]!=a[k][l]&&(u<=1||v<=1)){
if (u<=1) f[a[i][j]][a[k][l]]=min(f[a[i][j]][a[k][l]],v-1);
else if (v<=1) f[a[i][j]][a[k][l]]=min(f[a[i][j]][a[k][l]],u-1);
f[a[k][l]][a[i][j]]=f[a[i][j]][a[k][l]];
}
}
//	for (int i=1;i<=tot;++i)
//	  for (int j=1;j<=tot;++j)
//	    if (f[i][j]==0) f[i][j]=707406378;
/*	for (int i=1;i<=tot;++i){
for (int j=1;j<=tot;++j)
printf("%d ",f[i][j]);
printf("\n");
}*/
num=tot-1;
for (int i=1;i<=tot;++i){
pd=false;
for (int j=1;j<=tot;++j)
if (f[i][j]!=707406378){
pd=true; break;
}
if (pd==false) num--;
}
num=max(num,0);
if (num==0){
printf("0 0"); return 0;
}
printf("%d ",num);
for (int i=1;i<tot;++i)
for (int j=i+1;j<=tot;++j)
if (i!=j&&f[i][j]!=707406378){
side++;
b[side].x=i; b[side].y=j; b[side].z=f[i][j];
}
//	for (int i=1;i<=side;++i)
//	  printf("%d %d %d\n",b[i].x,b[i].y,b[i].z);
sort(b+1,b+side+1,cmp);
for (int i=1;i<=tot;++i) fa[i]=i;
for (int i=1;i<=side;++i){
if (find(b[i].x)!=find(b[i].y)){
merge(b[i].x,b[i].y);
sum++; sidesum+=b[i].z;
if (num==sum){
printf("%d\n",sidesum);
return 0;
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: