无向二分图的最小路径覆盖 = 顶点数 – 最大二分匹配数/2
看题解过的。看了网上的题解,说是拆点,然后把所有的城市分为两个集合,然后用匈牙利算法计算出最大二分图匹配。
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 char str[51][51]; 5 int p[501][501],used[501],linker[501],o[51][51]; 6 int x[4] = {0,0,1,-1}; 7 int y[4] = {1,-1,0,0}; 8 int num; 9 int dfs(int x) 10 { 11 int i; 12 for(i = 1;i <= num;i ++) 13 { 14 if(p[x][i]&&!used[i]) 15 { 16 used[i] = 1; 17 if(linker[i] == -1||dfs(linker[i])) 18 { 19 linker[i] = x; 20 return 1; 21 } 22 } 23 } 24 return 0; 25 } 26 int main() 27 { 28 int t,i,j,k,ans,n,m,r,c; 29 scanf("%d",&t); 30 while(t--) 31 { 32 memset(p,0,sizeof(p)); 33 memset(o,0,sizeof(o)); 34 memset(linker,-1,sizeof(linker)); 35 scanf("%d%d",&n,&m); 36 num = 1; 37 for(i = 0;i < n;i ++) 38 scanf("%s",str[i]); 39 for(i = 0;i < n;i ++) 40 { 41 for(j = 0;j < m;j ++) 42 { 43 if(str[i][j] == '*') 44 o[i][j] = num ++; 45 } 46 } 47 num --; 48 for(i = 0;i < n;i ++) 49 { 50 for(j = 0;j < m;j ++) 51 { 52 if(str[i][j] == '*') 53 { 54 for(k = 0;k <= 3;k ++) 55 { 56 r = i + x[k]; 57 c = j + y[k]; 58 if(r >= 0&&r < n&&c >= 0&&c < m&&o[r][c]) 59 { 60 p[o[r][c]][o[i][j]] = 1; 61 } 62 } 63 } 64 } 65 } 66 ans = 0; 67 for(i = 1;i <= num;i ++) 68 { 69 memset(used,0,sizeof(used)); 70 if(dfs(i)) 71 ans ++; 72 } 73 printf("%d\n",num-ans/2); 74 } 75 return 0; 76 }