T1002 搭桥 codevs
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题目描述 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
见描述
1 #include <algorithm> 2 #include <iostream> 3 #include <cstdio> 4 #include <cmath> 5 6 #define N 10015 7 8 using namespace std; 9 10 int r,c,num,cnt; 11 int bridge,tot,building; 12 int fa[N*10]; 13 char s; 14 15 struct node_map 16 { 17 int x,y; 18 }map[N*10]; 19 20 struct node_edge 21 { 22 int from,to,dis; 23 }edge[N*10]; 24 25 void init() 26 { 27 for(int i=1;i<=r*c;i++) 28 fa[i]=i; 29 } 30 31 int find(int x) 32 { 33 if(fa[x]!=x) 34 return fa[x]=find(fa[x]); 35 return fa[x]; 36 } 37 38 void add(int from,int to,int dis) 39 { 40 cnt++; 41 edge[cnt].from=from; 42 edge[cnt].to=to; 43 edge[cnt].dis=dis; 44 } 45 46 void work(int a,int b) 47 { 48 int dis_x=abs(map[a].x-map[b].x); 49 int dis_y=abs(map[a].y-map[b].y); 50 if(dis_x>=2&&dis_y>=2) return ; 51 if((dis_x<=1&&dis_y<=1)) 52 if(find(a)==find(b)) return ; 53 else 54 fa[find(a)]=find(b); 55 if(dis_x>=2) add(a,b,dis_x-1); 56 else add(a,b,dis_y-1); 57 } 58 59 bool cmp(node_edge a,node_edge b) 60 { 61 return a.dis<b.dis; 62 } 63 64 void kruskal() 65 { 66 sort(edge+1,edge+cnt+1,cmp); 67 for(int i=1;i<=cnt;i++) 68 { 69 int fa_x=find(edge[i].from),fa_y=find(edge[i].to); 70 if(fa_x!=fa_y) 71 { 72 bridge++; 73 fa[fa_x]=fa_y; 74 tot+=edge[i].dis; 75 } 76 } 77 } 78 79 int main() 80 { 81 scanf("%d%d",&r,&c); 82 init(); 83 for(int i=1;i<=r;i++) 84 for(int j=1;j<=c;j++) 85 { 86 cin>>s; 87 if(s=='#') 88 { 89 num++; 90 map[num].x=i; 91 map[num].y=j; 92 for(int k=1;k<num;k++) work(k,num); 93 } 94 } 95 for(int i=1;i<=num;i++) 96 if(i==fa[i]) building++; 97 kruskal(); 98 printf("%d\n%d %d",building,bridge,tot); 99 return 0; 100 }
——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。