继续我的刷题之路。。。
*题目描述 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
数据范围及提示 Data Size & Hint
见描述*
噫。
首先,dfs求联通块,just like 球细胞个数
v[][]表示每个点所在联通块的编号;
考虑对于每个点,有12个方向上的点可以链接。
所以,枚举这条直线上所有点
b[][]表示两个联通块之间最短的边
之后跑克鲁斯卡尔
求最小生成树;
得到答案~!~!~!~
代码!:~
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<cstdlib>
#include<string>
#include<bitset>
#include<iomanip>
#include<deque>
#define INF 1000000000
#define fi first
#define se second
#define N 100005
#define P 1000000007
#define debug(x) cerr<<#x<<"="<<x<<endl
#define MP(x,y) make_pair(x,y)
using namespace std;
int n,m,a[51][51],v[1001][1001],f[1001],ans=0;
int b[1001][1001];
int kk=1;
int fx[9]={0,1,1,1,-1,-1,-1,0,0};
int fy[9]={0,1,0,-1,1,0,-1,1,-1};
int find(int x)
{
return x==f[x] ? x:f[x]=find(f[x]);
}
struct zqm
{
int x,y,s;
}q[100001];
inline int get_num()
{
int num = 0;
char c;
bool flag = false;
while ((c = getchar()) == ' ' || c == '\n' || c == '\r');
if (c == '-') flag = true;
else num = c - '0';
while (isdigit(c = getchar()))
num = num * 10 + c - '0';
return (flag ? -1 : 1) * num;
} //忽略这一堆没用的读入优化
void dfs(int x,int y)
{
for(int i=1;i<=8;i++)
{
int tx=x+fx[i],ty=y+fy[i];
if(!v[tx][ty]&&a[tx][ty]&&tx>0&&tx<=n&&ty>0&&ty<=m)
{
v[tx][ty]=kk;
dfs(tx,ty);
}
}
}
bool cmp(zqm a ,zqm b)
{
return a.s<b.s;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
char c;
cin>>c;
if(c=='.')a[i][j]=0;
else a[i][j]=1;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(!v[i][j]&&a[i][j])
{
v[i][j]=kk;
dfs(i,j);
kk++;
}
}
}
kk--;
cout<<kk;
cout<<endl;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
for(int k=i-2;k>=1;k--)
{
for(int l=j-1;l<=j+1;l++)
{
if(b[v[i][j]][v[k][l]]==0)
{
b[v[i][j]][v[k][l]]=1000;
}
b[v[i][j]][v[k][l]]=min(b[v[i][j]][v[k][l]],i-k-1);
b[v[k][l]][v[i][j]]=b[v[i][j]][v[k][l]];
}
}
for(int k=i+2;k<=n;k++)
{
for(int l=j-1;l<=j+1;l++)
{
if(b[v[i][j]][v[k][l]]==0)
{
b[v[i][j]][v[k][l]]=1000;
}
b[v[i][j]][v[k][l]]=min(b[v[i][j]][v[k][l]],k-i-1);
b[v[k][l]][v[i][j]]=b[v[i][j]][v[k][l]];
}
}
for(int k=i-1;k<=i+1;k++)
{
for(int l=1;l<=j-2;l++)
{
if(b[v[i][j]][v[k][l]]==0)
{
b[v[i][j]][v[k][l]]=1000;
}
b[v[i][j]][v[k][l]]=min(b[v[i][j]][v[k][l]],j-l-1);
b[v[k][l]][v[i][j]]=b[v[i][j]][v[k][l]];
}
}
for(int k=i-1;k<=i+1;k++)
{
for(int l=j+2;l<=m;l++)
{
if(b[v[i][j]][v[k][l]]==0)
{
b[v[i][j]][v[k][l]]=1000;
}
b[v[i][j]][v[k][l]]=min(b[v[i][j]][v[k][l]],l-j-1);
b[v[k][l]][v[i][j]]=b[v[i][j]][v[k][l]];
}
}
}
}
int p=0;
/*for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cout<<v[i][j]<< " ";
}cout<<endl;
}*/
for(int i=1;i<=kk;i++)
{
for(int j=1;j<=kk;j++)
{
//cout<<b[i][j]<< " ";
p++;
q[p].x=i;
q[p].y=j;
q[p].s=b[i][j];
}//cout<<endl;
}
sort(q+1,q+1+p,cmp);
for(int i=1;i<=kk;i++)
{
f[i]=i;
}
int pp=kk;
for(int i=1;i<=p;i++)
{
if(q[i].s&&find(f[q[i].x])!=find(f[q[i].y]))
{
kk--;
ans+=q[i].s;
f[find(q[i].x)]=find(f[q[i].y]);
if(kk==1)
{
break;
}
}
}
cout<<pp-kk<< " "<<ans<<endl;
}
噫
话说为啥我上传不了图片。