繼續我的刷題之路。。。
*題目描述 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;
}
噫////
話說爲啥我上傳不了圖片。