http://poj.org/problem?id=3020
最小路径覆盖,拆点,总结点数 = 匹配数*2+未匹配节点,所以所用天线数就等于匹配数+未匹配数=总结点-匹配数。
由于拆点后,多加了边,匹配数变成了原来的2倍,有向图-》无向图,匹配数增加的是一样的。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 using namespace std; 6 int link[500],map[500][500],ma[500][500],vis[500],dir1[4]={0,0,-1,1},dir2[4]={-1,1,0,0}; 7 int find(int x,int n) 8 { 9 int i,j; 10 for(i = 1; i <= n ; i++) 11 { 12 if(ma[x][i]&&!vis[i]) 13 { 14 vis[i] = 1; 15 if(link[i]==0||find(link[i],n)) 16 { 17 link[i] = x; 18 return 1; 19 } 20 } 21 } 22 return 0; 23 } 24 int main() 25 { 26 int i,j,k,n,m,t; 27 char a; 28 cin>>t; 29 while(t--) 30 { 31 memset(map,0,sizeof(map)); 32 memset(link,0,sizeof(link)); 33 memset(ma,0,sizeof(ma)); 34 cin>>n>>m; 35 int g = 0; 36 for(i = 1; i <= n ; i++) 37 { 38 getchar(); 39 for(j = 1; j <= m ; j++) 40 { 41 scanf("%c", &a); 42 if(a=='*') 43 { 44 g++; 45 map[i][j] = g; 46 } 47 } 48 } 49 for(i =1; i <= n ; i++) 50 for(j = 1; j <= m ; j++) 51 { 52 if(map[i][j]>0) 53 { 54 int k1 = map[i][j]; 55 for(k = 0 ; k < 4 ; k++) 56 { 57 int x = i+dir1[k]; 58 int y = j+dir2[k]; 59 if(x>0&&x<=n&&y>0&&y<=m) 60 { 61 int k2 = map[x][y]; 62 ma[k1][k2] = 1; 63 } 64 } 65 } 66 } 67 int sum = 0; 68 for(i = 1; i <= g ; i++) 69 { 70 memset(vis,0,sizeof(vis)); 71 if(find(i,g)) 72 sum++; 73 } 74 cout<<g-sum/2<<endl; 75 } 76 return 0; 77 }