题目:http://poj.org/problem?id=3020
这个题主要是构图比较难,处理方法是把城市编号然后如果在上下左右四个方向存在城市的话,那么这两个城市就可以组成一条边,构成的图是一个无向图,
DAG图的最小路径覆盖 = 节点数(n)- 最大匹配数;
无向图的最小路径覆盖=节点数(n)-最大匹配数/2;
代码:
View Code
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int map[405][405]; 6 int st[45][15]; 7 int vis[405]; 8 int link[405]; 9 int num; 10 int n,m; 11 int dire[4][2]={{0,1},{1,0},{-1,0},{0,-1}}; 12 int find(int x) 13 { 14 int i; 15 for(i=1;i<=num;i++) 16 { 17 if(!vis[i]&&map[x][i]) 18 { 19 vis[i]=1; 20 if(link[i]==0||find(link[i])) 21 { 22 link[i]=x; 23 return 1; 24 } 25 } 26 } 27 return 0; 28 } 29 int main() 30 { 31 int t,i,j,k,su; 32 char c; 33 scanf("%d",&t); 34 while(t--) 35 { 36 memset(st,0,sizeof(st)); 37 memset(map,0,sizeof(map)); 38 memset(link,0,sizeof(link)); 39 scanf("%d%d",&n,&m); 40 num=0; 41 getchar(); 42 for(i=1;i<=n;i++) 43 { 44 for(j=1;j<=m;j++) 45 { 46 scanf("%c",&c); 47 if(c=='*') 48 { 49 num++; 50 st[i][j]=num; 51 } 52 } 53 getchar(); 54 } 55 for(i=1;i<=n;i++) 56 { 57 for(j=1;j<=m;j++) 58 { 59 if(st[i][j]!=0) 60 { 61 for(k=0;k<4;k++) 62 { 63 if(st[i+dire[k][0]][j+dire[k][1]]!=0) 64 { 65 map[st[i][j]][st[i+dire[k][0]][j+dire[k][1]]]=1; 66 } 67 } 68 } 69 } 70 } 71 su=0; 72 for(i=1;i<=num;i++) 73 { 74 memset(vis,0,sizeof(vis)); 75 if(find(i)) 76 su++; 77 } 78 printf("%d\n",num-(su/2)); 79 } 80 return 0; 81 }