1. 程式人生 > >codevs 1002 搭橋

codevs 1002 搭橋

clu style edi fin int operator ans 輸入 pri

題目描述 Description

有一矩形區域的城市中建築了若幹建築物,如果某兩個單元格有一個點相聯系,則它們屬於同一座建築物。現在想在這些建築物之間搭建一些橋梁,其中橋梁只能沿著矩形的方格的邊沿搭建,如下圖城市1有5棟建築物,可以搭建4座橋將建築物聯系起來。城市2有兩座建築物,但不能搭建橋梁將它們連接。城市3只有一座建築物,城市4有3座建築物,可以搭建一座橋梁聯系兩棟建築物,但不能與第三座建築物聯系在一起。

技術分享 輸入描述 Input Description

在輸入的數據中的第一行包含描述城市的兩個整數rc, 分別代表從北到南、從東到西的城市大小(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可以解決第一問;

第二問用最小生成樹做

  1 #include<cstdio>
  2 #include<iostream>
  3
#include<algorithm> 4 using namespace std; 5 6 string s; 7 8 int dx[9]={0,0,0,1,-1,1,1,-1,-1},dy[9]={0,1,-1,0,0,1,-1,1,-1}; 9 10 int book[55][55],pos[55][55]; 11 const int N=2505; 12 int father[N*2]; 13 14 struct node{ 15 int u,v,w; 16 bool operator < (const node &a)const 17 { 18 return w<a.w; 19 } 20 }e[N*100]; 21 int map[55][55]; 22 23 int n,m; 24 int ans=0,cnt=0; 25 26 27 void dfs(int x,int y) 28 { 29 book[x][y]=ans; 30 for(int i=0;i<=8;i++) 31 { 32 if(map[x+dx[i]][y+dy[i]]) 33 { 34 map[x+dx[i]][y+dy[i]]=0; 35 dfs(x+dx[i],y+dy[i]); 36 } 37 } 38 return ; 39 40 } 41 42 bool unionn(int x1,int y1,int x2,int y2,int w) 43 { 44 if(y2<1||y2>m||x2<1||x2>n||!book[x2][y2]) return 1; 45 if(book[x1][y1]==book[x2][y2]) return 0; 46 cnt++; 47 e[cnt].u=book[x1][y1]; 48 e[cnt].v=book[x2][y2]; 49 e[cnt].w=w-1; 50 return 1; 51 } 52 53 void build(int x ,int y) 54 { 55 for(int i=x+1; i<=n; i++) 56 if(!unionn(x,y,i,y,i-x)||!unionn(x,y,i,y+1,i-x)||!unionn(x,y,i,y-1,i-x)) 57 break; 58 for(int i=x-1; i>0; i--) 59 if(!unionn(x,y,i,y,x-i)||!unionn(x,y,i,y+1,x-i)||!unionn(x,y,i,y-1,x-i)) 60 break; 61 for(int i=y+1; i<=m; i++) 62 if(!unionn(x,y,x,i,i-y)||!unionn(x,y,x-1,i,i-y)||!unionn(x,y,x+1,i,i-y)) 63 break; 64 for(int i=y-1; i>0; i--) 65 if(!unionn(x,y,x,i,y-i)||!unionn(x,y,x-1,i,y-i)||!unionn(x,y,x-1,i,y-i)) 66 break; 67 } 68 69 void work() 70 { 71 for(int i=1;i<=n;i++) 72 for(int j=1;j<=m;j++) 73 { 74 if(pos[i][j])build(i,j); 75 } 76 return ; 77 } 78 79 int find(int x) 80 { 81 if(father[x]!=x)father[x]=find(father[x]); 82 return father[x]; 83 } 84 85 int main() 86 { 87 scanf("%d%d",&n,&m); 88 for(int i=1;i<=n*m;i++)father[i]=i; 89 for(int i=1;i<=n;i++) 90 { 91 cin>>s; 92 for(int j=0;j<s.size();j++) 93 { 94 if(s[j]==#)pos[i][j+1]=map[i][j+1]=1; 95 else map[i][j+1]=0; 96 //if(map[i][j+1]==1&&map[i-1][j+1]==0&&map[i][j]==0)cnt++; 97 } 98 99 } 100 //printf("%d",cnt); 101 for(int i=1;i<=n;i++) 102 for(int j=1;j<=m;j++) 103 { 104 if(map[i][j]==1) 105 { 106 map[i][j]=0; 107 dfs(i,j); 108 ans++; 109 } 110 } 111 printf("%d\n",ans); 112 int sum=0; 113 for(int i=1;i<=ans;i++)father[i]=i; 114 work(); 115 sort(e+1,e+cnt+1); 116 ans=0; 117 for(int i=1;i<=cnt;i++) 118 { 119 int p=find(e[i].u),q=find(e[i].v); 120 if(p!=q) 121 { 122 father[p]=q; 123 ans++; 124 sum+=e[i].w; 125 } 126 } 127 printf("%d %d",ans,sum); 128 129 return 0; 130 131 }

codevs 1002 搭橋