http://poj.org/problem?id=2226
模板抄错,结果错了一下午。将连续横行上的*和连续纵桁上点分别看做两个点集,连接两集合中点的边就是图中的点。即求最小顶点覆盖最多的边。最小点覆盖=最大匹配。
有篇图片的讲解,挺好,很形象。http://ip96cns.blog.163.com/blog/static/170095192201117465473/
View Code
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int map[1000][1000]; 6 int r,c,link[1000],vis[1000]; 7 int find(int x,int n)//二分匹配模板 8 { 9 int i,j; 10 for(i = 1; i <= n ; i++) 11 { 12 if(map[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,a[100][100],b[100][100]; 27 char s[100][100]; 28 while(cin>>r>>c) 29 { 30 memset(link,0,sizeof(link)); 31 32 memset(map,0,sizeof(map)); 33 k = 0; 34 int sum = 0; 35 int ii=1,jj=1; 36 for(i = 1 ; i <= r ; i++) 37 { 38 getchar(); 39 for(j = 1; j <= c ; j++) 40 { 41 scanf("%c", &s[i][j]); 42 } 43 } 44 for(i = 1; i <= r ; i++) 45 for(j = 1; j <= c ; j++)//建立X集合中的点 46 { 47 if(j==1&&i!=1&&s[i-1][c]=='*') 48 ii++; 49 if(s[i][j]=='*') 50 { 51 a[i][j] = ii; 52 } 53 if(j!=c&&(s[i][j]=='*'&&s[i][j+1]!='*')) 54 ii++; 55 } 56 for(i = 1; i <= c ; i++)//建立Y集合中的点 57 for(j = 1; j <= r ; j++) 58 { 59 if((j==1&&i!=1&&s[r][i-1]=='*')) 60 jj++; 61 if(s[j][i]=='*') 62 b[j][i] = jj; 63 if(j!=r&&(s[j][i]=='*'&&s[j+1][i]!='*')) 64 { 65 jj++; 66 } 67 } 68 for(i = 1; i <= r ; i++) 69 for(j = 1; j <= c ; j++)//建立连接两集合点的边,即图中的"*" 70 { 71 if(s[i][j]=='*') 72 { 73 map[a[i][j]][b[i][j]] = 1; 74 } 75 } 76 for(i = 1; i <= ii ; i++) 77 { 78 memset(vis,0,sizeof(vis)); 79 if(find(i,jj))//寻找最大匹配 80 { 81 sum++; 82 } 83 } 84 cout<<sum<<endl; 85 } 86 return 0; 87 }