codevs1002: 搭桥
题目描述 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
见描述
题解
暴力出奇迹,建边以后kruskal,码农题啊。。。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define maxn 60 5 using namespace std; 6 int u[10]={0,0,1,-1,1,1,-1,-1},p[10]={1,-1,0,0,-1,1,-1,1}; 7 int ux[20]={2,-2,0,0,2,2,-2,-2,1,-1,1,-1},px[20]={0,0,2,-2,1,-1,1,-1,2,2,-2,-2}; 8 int fa[maxn*maxn],a[maxn][maxn]; 9 int n,m,ans,answ,ecnt,head[maxn*maxn]; 10 char str[60]; 11 struct edge{ 12 int u,v,w,next; 13 }E[maxn*maxn*4]; 14 void add(int u,int v,int w) 15 { 16 E[++ecnt].u=u; 17 E[ecnt].v=v; 18 E[ecnt].w=w; 19 E[ecnt].next=head[u]; 20 head[u]=ecnt; 21 } 22 bool ok(int x,int y) 23 { 24 if(x<1||y<1||x>n||y>m)return false; 25 return true; 26 } 27 int find(int x) 28 { 29 return x==fa[x]?x:fa[x]=find(fa[x]); 30 } 31 void build(int x,int y,int z) 32 { 33 for(int i=x ; i>=1 ; --i) 34 if(a[i][y]) 35 { 36 int fy=find((i-1)*m+y); 37 if(z!=fy) 38 { 39 add(z,(i-1)*m+y,x-i-1); 40 break; 41 } 42 } 43 for(int i=y ; i>=1 ; --i) 44 if(a[x][i]) 45 { 46 int fy=find((x-1)*m+i); 47 if(z!=fy) 48 { 49 add(z,(x-1)*m+i,y-i-1); 50 break; 51 } 52 } 53 for(int i=x ; i>=1 ; --i) 54 if(a[i][y+1]&&y<m) 55 { 56 int fy=find((i-1)*m+y+1); 57 if(z!=fy) 58 { 59 add(z,(i-1)*m+y+1,x-i-1); 60 break; 61 } 62 } 63 for(int i=x ; i>=1 ; --i) 64 if(a[i][y-1]&&y>1) 65 { 66 int fy=find((i-1)*m+y-1); 67 if(z!=fy) 68 { 69 add(z,(i-1)*m+y-1,x-i-1); 70 break; 71 } 72 } 73 for(int i=y ; i>=1 ; --i) 74 if(a[x-1][i]&&x>1) 75 { 76 int fy=find((x-2)*m+i); 77 if(z!=fy) 78 { 79 add(z,(x-2)*m+i,y-i-1); 80 break; 81 } 82 } 83 for(int i=y ; i>=1 ; --i) 84 if(a[x+1][i]&&x<n) 85 { 86 int fy=find(x*m+i); 87 if(z!=fy) 88 { 89 add(z,x*m+i,y-i-1); 90 break; 91 } 92 } 93 } 94 bool cmp(edge x,edge y) 95 { 96 return x.w<y.w; 97 } 98 int main() 99 { 100 scanf("%d%d",&n,&m); 101 for(int i=1 ; i<=n ; ++i) 102 { 103 for(int j=1 ; j<=m ; ++j) 104 fa[(i-1)*m+j]=(i-1)*m+j; 105 } 106 for(int i=1 ; i<=n ; ++i) 107 { 108 scanf("%s",str+1); 109 for(int j=1 ; j<=m ; ++j) 110 { 111 if(str[j]=='#') 112 { 113 a[i][j]=1; 114 ++ans; 115 } 116 } 117 } 118 for(int i=1 ; i<=n ; ++i ) 119 for(int j=1 ; j<=m ; ++j ) 120 { 121 if(!a[i][j])continue; 122 for(int k=0 ; k<8 ; ++k) 123 { 124 int dx=i+u[k];int dy=j+p[k]; 125 if(ok(dx,dy)&&a[dx][dy]) 126 { 127 int fx=find((i-1)*m+j); 128 int fy=find((dx-1)*m+dy); 129 if(fx!=fy) 130 { 131 --ans; 132 fa[fy]=fx; 133 } 134 } 135 } 136 } 137 printf("%d\n",ans); 138 ans=0; 139 for(int i=1 ; i<=n ; ++i ) 140 for(int j=1 ; j<=m ; ++j ) 141 { 142 if(!a[i][j])continue; 143 int tmp=find((i-1)*m+j); 144 build(i,j,tmp); 145 } 146 sort(E+1,E+1+ecnt,cmp); 147 for(int i=1 ; i<=ecnt ; ++i) 148 { 149 int u=E[i].u; 150 int v=E[i].v; 151 int fx=find(u);int fy=find(v); 152 if(fx!=fy) 153 { 154 ++ans; 155 answ+=E[i].w; 156 fa[fy]=fx; 157 } 158 } 159 printf("%d %d",ans,answ); 160 return 0; 161 }