• “金山-讯飞”杯2024年武汉理工大学程序设计竞赛 A. Mobiusp败走***(思维题-点双连通分量、连通性)


    题目

    思路来源

    官方题解

    题解

    手玩发现,能换的话,当且仅当.和1在一个环里,而这就是点双连通分量

    所以最优策略是先把.换到(x,y)的位置,然后判断.和1在不在一个环里

    也就是:

    1. 判断删掉1时,.和(x,y)联通

    2. 判断(x,y)和1在同一个连通分量里

    这个和三者在同一个连通分量不等价,可以参考下图:

    .和1并不在一个点双里,但是可以先把.换到(1,2)的位置里,使之在同一个点双里

    3 3

    1 2

    #**
    **1
    .##

    代码

    1. #include
    2. using namespace std;
    3. #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    4. #define per(i,a,b) for(int i=(a);i>=(b);--i)
    5. typedef long long ll;
    6. typedef double db;
    7. typedef pair<int,int> P;
    8. #define fi first
    9. #define se second
    10. #define pb push_back
    11. #define dbg(x) cerr<<(#x)<<":"<" ";
    12. #define dbg2(x) cerr<<(#x)<<":"<
    13. #define SZ(a) (int)(a.size())
    14. #define sci(a) scanf("%d",&(a))
    15. #define pt(a) printf("%d",a);
    16. #define pte(a) printf("%d\n",a)
    17. #define ptlle(a) printf("%lld\n",a)
    18. #define debug(...) fprintf(stderr, __VA_ARGS__)
    19. using namespace std;
    20. const int N=1500*1500+5,M=1500*1500*4+5,K=1502;
    21. int n,m,u,v,ex,ey,blk,one,ed;
    22. int low[N],dfn[N],tot,tp,cnt;
    23. vector

      stk;

    24. bool vis[N];
    25. char s[K][K];
    26. vector<int>e[N];
    27. int f(int x,int y){
    28. return x*m+y;
    29. }
    30. void add(int x,int y){
    31. e[x].pb(y);
    32. }
    33. bool dfs(int u,int fa){
    34. low[u]=dfn[u]=++tot;
    35. int ch=0;
    36. for(auto &v:e[u]){
    37. if(!dfn[v]){
    38. stk.pb(P(u,v));//记录当前BCC的边
    39. if(dfs(v,u))return 1;
    40. ch++;//从u这里向下dfs的子树的数量
    41. low[u]=min(low[u],low[v]);
    42. if(low[v]>=dfn[u]){//割点u
    43. bool ok1=0,ok2=0;
    44. for(;;){
    45. P x=stk.back();stk.pop_back();
    46. int y=x.fi,z=x.se;
    47. ok1|=(y==one);
    48. ok2|=(y==ed);
    49. ok1|=(z==one);
    50. ok2|=(z==ed);
    51. //printf("one:%d ed:%d\n",y,z);
    52. if(ok1 && ok2)return 1;
    53. if(y==u && z==v)break;
    54. }
    55. }
    56. }
    57. else if(v!=fa && dfn[v]
    58. stk.pb(P(u,v));
    59. low[u]=min(low[u],dfn[v]);
    60. }
    61. }
    62. return 0;
    63. }
    64. bool dfs2(int u){
    65. vis[u]=1;
    66. if(u==blk)return 1;
    67. for(auto &v:e[u]){
    68. if(vis[v] || v==one)continue;
    69. if(dfs2(v))return 1;
    70. }
    71. return 0;
    72. }
    73. bool sol(){
    74. sci(n),sci(m);
    75. sci(ex);sci(ey);
    76. ex--;ey--;
    77. rep(i,0,n-1){
    78. scanf("%s",s[i]);
    79. }
    80. rep(i,0,n-1){
    81. rep(j,0,m-1){
    82. if(s[i][j]=='#')continue;
    83. int x=f(i,j);
    84. if(s[i][j]=='1')one=x;
    85. if(s[i][j]=='.')blk=x;
    86. if(i-1>=0 && s[i-1][j]!='#'){
    87. int y=f(i-1,j);
    88. //printf("x:%d y:%d\n",x,y);
    89. add(x,y);add(y,x);
    90. }
    91. if(j-1>=0 && s[i][j-1]!='#'){
    92. int y=f(i,j-1);
    93. //printf("x2:%d y2:%d\n",x,y);
    94. add(x,y);add(y,x);
    95. }
    96. }
    97. }
    98. ed=f(ex,ey);
    99. if(one==ed)return 1;
    100. if(!dfs2(ed))return 0;
    101. rep(i,0,n-1){
    102. rep(j,0,m-1){
    103. if(s[i][j]=='#')continue;
    104. int x=f(i,j);
    105. if(!dfn[x] && dfs(x,-1))return 1;
    106. }
    107. }
    108. return 0;
    109. }
    110. int main(){
    111. puts(sol()?"Yes":"No");
    112. return 0;
    113. }

  • 相关阅读:
    二进制逻辑运算和基本门电路
    Anaconda与Python环境在Windows中的部署
    Java数据库连接 (Java Database connect)
    .NET 9 预览版 5 发布
    JavaEE 网络原理——TCP的工作机制(初篇 包含 UDP 协议的再次阐述)
    本周讨论用户体验:Daedalus 的 Nemo 加入 Ambire,探索加密海洋
    OpenJudge NOI 2.1 1816:拨钟问题
    达梦数据库安装使用教程系列(五)
    爱普生机器人修改IP
    webpack打包gz文件,nginx开启gzip压缩
  • 原文地址:https://blog.csdn.net/Code92007/article/details/140338720