T1002 搭桥 codevs

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 黄金 Gold
题目描述 Description

有一矩形区域的城市中建筑了若干建筑物,如果某两个单元格有一个点相联系,则它们属于同一座建筑物。现在想在这些建筑物之间搭建一些桥梁,其中桥梁只能沿着矩形的方格的边沿搭建,如下图城市1有5栋建筑物,可以搭建4座桥将建筑物联系起来。城市2有两座建筑物,但不能搭建桥梁将它们连接。城市3只有一座建筑物,城市4有3座建筑物,可以搭建一座桥梁联系两栋建筑物,但不能与第三座建筑物联系在一起。

输入描述 Input Description

在输入的数据中的第一行包含描述城市的两个整数r 和c, 分别代表从北到南、从东到西的城市大小(1 <= <= 50 and 1 <=  c <= 50). 接下来的r 行, 每一行由个(“#”)和(“.”)组成的字符. 每一个字符表示一个单元格。“#”表示建筑物,“.”表示空地。

输出描述 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
%d %d",building,bridge,tot);
 99     return 0;
100 }
——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。
原文地址:https://www.cnblogs.com/Shy-key/p/6670764.html