记录编号 369433 评测结果 AAAAAAAAAA
题目名称 [CodeChef MINESREV] 扫雷反转 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 0.062 s
提交时间 2017-02-09 13:57:17 内存使用 3.42 MiB
显示代码纯文本
  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<queue>
  4. using namespace std;
  5. const int N=1e5+10;
  6. int T,n,m,cnt;
  7. char s[110][110];
  8. int fa[N],color[N],tp[N],next[N],match[N];
  9. int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
  10. void unit(int x,int y){fa[find(x)]=find(y);}
  11. queue<int> Q;
  12. vector<int> E[N];
  13. int lca(int x,int y){
  14. static int C=0;C++;
  15. for (;;swap(x,y))
  16. if (x){
  17. x=find(x);
  18. if (color[x]==C) return x;
  19. color[x]=C;
  20. x=next[match[x]];
  21. }
  22. }
  23. void group(int a,int p){
  24. while (a!=p){
  25. int b=match[a],c=next[b];
  26. if (find(c)!=p) next[c]=b;
  27. if (tp[a]!=1) tp[a]=1,Q.push(a);
  28. if (tp[b]!=1) tp[b]=1,Q.push(a);
  29. unit(a,b);unit(b,c);
  30. a=c;
  31. }
  32. }
  33. bool bfs(int s){
  34. while (!Q.empty()) Q.pop();
  35. for (int i=1;i<=cnt;i++) fa[i]=i,next[i]=tp[i]=0;
  36. tp[s]=1;Q.push(s);
  37. while (!Q.empty()){
  38. int x=Q.front();Q.pop();
  39. for (int i=E[x].size()-1;i>=0;i--){
  40. int y=E[x][i];
  41. if (tp[y]==2||find(x)==find(y)) continue;
  42. if (!match[y]){
  43. next[y]=x;
  44. for (int i=y;i;){
  45. int u=next[i],v=match[u];
  46. match[i]=u;match[u]=i;
  47. i=v;
  48. }
  49. return 1;
  50. }
  51. if (tp[y]==1){
  52. int p=lca(x,y);
  53. if (find(x)!=p) next[x]=y;
  54. if (find(y)!=p) next[y]=x;
  55. group(x,p);
  56. group(y,p);
  57. }
  58. else{
  59. next[y]=x;tp[y]=2;
  60. tp[match[y]]=1;
  61. Q.push(match[y]);
  62. }
  63. }
  64. }
  65. return 0;
  66. }
  67. const int fx[8]={1,1,1,0,0,-1,-1,-1},fy[8]={1,0,-1,1,-1,1,0,-1};
  68. int vis[110][110];
  69. void flood(int x,int y){
  70. if (vis[x][y]||s[x][y]!=1) return;
  71. vis[x][y]=cnt;
  72. for (int k=0;k<8;k++) flood(x+fx[k],y+fy[k]);
  73. }
  74. int main()
  75. {
  76. freopen("MINESREV.in","r",stdin);
  77. freopen("MINESREV.out","w",stdout);
  78. scanf("%d",&T);
  79. while (T--){
  80. int ans=0;
  81. scanf("%d%d",&n,&m);
  82. for (int i=1;i<=cnt;i++)
  83. E[i].clear(),match[i]=0;
  84. cnt=0;
  85. for (int i=1;i<=n;i++) scanf("%s",s[i]+1);
  86. for (int i=1;i<=n;i++)
  87. for (int j=1;j<=m;j++){
  88. vis[i][j]=0;
  89. if (s[i][j]=='.'){
  90. s[i][j]=1;
  91. for (int k=0;k<8;k++){
  92. int x=i+fx[k],y=j+fy[k];
  93. if (x&&x<=n&&y&&y<=m&&s[x][y]=='*') s[i][j]='.';
  94. }
  95. }
  96. if (s[i][j]=='*') ans++;
  97. }
  98. for (int i=1;i<=n;i++)
  99. for (int j=1;j<=m;j++){
  100. if (s[i][j]==1&&!vis[i][j])
  101. cnt++,ans++,flood(i,j);
  102. if (s[i][j]=='.'){
  103. ans++;
  104. for (int k=0;k<8;k++)
  105. if (s[i+fx[k]][j+fy[k]]==1){
  106. ans--;break;
  107. }
  108. }
  109. }
  110. for (int i=1;i<=n;i++)
  111. for (int j=1;j<=m;j++)
  112. if (s[i][j]=='.'){
  113. for (int k=0;k<8;k++){
  114. int x=i+fx[k],y=j+fy[k],c=vis[x][y];
  115. if (x&&x<=n&&y&&y<=m&&s[x][y]==1){
  116. for (int l=0;l<8;l++){
  117. int X=i+fx[l],Y=j+fy[l],C=vis[X][Y];
  118. if (X&&X<=n&&Y&&Y<=m&&s[X][Y]==1&&c!=C)
  119. E[c].push_back(C),E[C].push_back(c);
  120. }
  121. }
  122. }
  123. }
  124. for (int i=1;i<=cnt;i++)
  125. if (!match[i]) ans-=bfs(i);
  126. printf("%d\n",ans);
  127. }
  128. return 0;
  129. }