news 2026/7/16 5:37:59

题解:AcWing 237 程序自动分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
题解:AcWing 237 程序自动分析

【题目来源】

AcWing:237. 程序自动分析 - AcWing题库

【题目描述】

在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足。

考虑一个约束满足问题的简化版本:假设x 1 , x 2 , x 3 , … x_1,x_2,x_3,…x1,x2,x3,代表程序中出现的变量,给定n nn个形如x i = x j x_i=x_jxi=xjx i ≠ x j x_i≠x_jxi=xj的变量相等/不等的约束条件,请判定是否可以分别为每一个变量赋予恰当的值,使得上述所有约束条件同时被满足。

例如,一个问题中的约束条件为:x 1 = x 2 x_1=x_2x1=x2x 2 = x 3 x_2=x_3x2=x3x 3 = x 4 x_3=x_4x3=x4x 1 ≠ x 4 x_1≠x_4x1=x4,这些约束条件显然是不可能同时被满足的,因此这个问题应判定为不可被满足。

现在给出一些约束满足问题,请分别对它们进行判定。

【输入】

输入文件的第1 11行包含1 11个正整数t tt,表示需要判定的问题个数,注意这些问题之间是相互独立的。

对于每个问题,包含若干行:

1 11行包含1 11个正整数n nn,表示该问题中需要被满足的约束条件个数。

接下来n nn行,每行包括3 33个整数i , j , e i,j,ei,j,e,描述1 11个相等/不等的约束条件,相邻整数之间用单个空格隔开。若e = 1 e=1e=1,则该约束条件为x i = x j x_i=x_jxi=xj;若e = 0 e=0e=0,则该约束条件为x i ≠ x j x_i≠x_jxi=xj

【输出】

输出文件包括t tt行。

输出文件的第k kk行输出一个字符串YES或者NOYES表示输入中的第k kk个问题判定为可以被满足,NO表示不可被满足。

【输入样例】

2 2 1 2 1 1 2 0 2 1 2 1 2 1 1

【输出样例】

NO YES

【核心思想】

  1. 问题分析:给定t tt组测试数据,每组包含n nn个变量之间的相等(x i = x j x_i = x_jxi=xj)或不等(x i ≠ x j x_i \neq x_jxi=xj)约束条件,判断是否存在一种赋值方案使得所有约束同时满足。这是一个并查集问题,关键在于利用相等关系的传递性:若x i = x j x_i = x_jxi=xjx j = x k x_j = x_kxj=xk,则x i = x k x_i = x_kxi=xk

  2. 算法选择

    • 并查集(Disjoint Set Union, DSU):维护变量的等价类,支持O ( α ( n ) ) O(\alpha(n))O(α(n))的合并与查询
    • 离散化(Hash/Map):变量编号可能很大(达到10 9 10^9109),需要映射为连续的编号
    • 两遍扫描策略:先合并所有相等关系,再检查不等关系是否冲突
  3. 关键步骤

    • 离散化:使用unordered_map将原始变量值x , y x, yx,y映射为1 ∼ n 1 \sim n1n的连续编号
    • 初始化并查集p[i] = i,每个变量初始独立
    • 第一遍:处理相等约束e = 1 e = 1e=1):
      • 对于每个相等约束( x i , x j ) (x_i, x_j)(xi,xj)
        • pa = find(x_i),pb = find(x_j)
        • p[pa] = pb:将两个等价类合并
    • 第二遍:检查不等约束e = 0 e = 0e=0):
      • 对于每个不等约束( x i , x j ) (x_i, x_j)(xi,xj)
        • pa = find(x_i),pb = find(x_j)
        • pa == pb,说明x i x_ixix j x_jxj已在同一等价类,与不等约束矛盾,输出NO
    • 结果:若所有不等约束均不矛盾,输出YES
  4. 时间/空间复杂度

    • 时间复杂度:O ( m ⋅ α ( n ) ) O(m \cdot \alpha(n))O(mα(n)),其中m mm为约束条数,α \alphaα为阿克曼函数反函数,近似常数。离散化O ( m ) O(m)O(m),并查集操作O ( m ⋅ α ( n ) ) O(m \cdot \alpha(n))O(mα(n))
    • 空间复杂度:O ( n ) O(n)O(n),并查集父节点数组和离散化映射表
  5. 并查集的核心思想

    • 等价类维护:将相等的变量归入同一集合,利用路径压缩优化查询效率
    • 传递闭包:相等关系具有传递性,并查集天然支持这种闭包计算
    • 冲突检测策略:必须先处理所有相等关系(建立等价类),再检查不等关系。若顺序颠倒,可能导致错误判断
    • 离散化必要性:当变量范围极大而实际出现次数较少时,通过哈希映射压缩空间
    • 适用于变量分组、连通性判断、等价关系推理类问题

【算法标签】

#并查集

【代码详解】

#include<bits/stdc++.h>usingnamespacestd;constintN=200005;// 最大节点数(离散化后最多 n 个节点)intn,m,T;// n: 离散化后的节点计数, m: 约束条件个数, T: 测试用例数intp[N];// 并查集父节点数组unordered_map<int,int>S;// 离散化映射:原始变量值 -> 连续编号structQuery{intx,y,e;// x,y: 离散化后的变量编号, e: 约束类型(1相等,0不等)}query[N];// 存储所有约束条件// 离散化:将原始变量值映射为连续编号(从1开始)intget(intx){if(S.count(x)==0)S[x]=++n;// 若该值未出现过,分配新编号(n 从0递增)returnS[x];// 返回该变量对应的编号}// 并查集查找(路径压缩)intfind(intx){if(p[x]!=x)p[x]=find(p[x]);// 递归查找根节点并压缩路径returnp[x];// 返回根节点}intmain(){cin>>T;// 读入测试用例数while(T--)// 遍历每个测试用例{n=0;// 重置节点计数器(用于离散化)S.clear();// 清空离散化映射cin>>m;// 读入约束条件个数for(inti=1;i<=m;i++){intx,y,e;cin>>x>>y>>e;// 读入原始变量值和约束类型query[i]={get(x),get(y),e};// 离散化后存入查询数组}for(inti=1;i<=n;i++)p[i]=i;// 初始化并查集:每个节点自成一个集合// 第一遍:处理所有 "相等" 约束(e=1),合并对应集合for(inti=1;i<=m;i++){if(query[i].e==1){intpa=find(query[i].x),pb=find(query[i].y);p[pa]=pb;// 将 x 所在集合的根指向 y 所在集合的根}}// 第二遍:检查所有 "不等" 约束(e=0)是否产生矛盾boolhas_conflict=false;for(inti=1;i<=m;i++){if(query[i].e==0){intpa=find(query[i].x),pb=find(query[i].y);if(pa==pb)// 若原本应不等的两个变量已在同一集合{has_conflict=true;// 发现矛盾,约束不可同时满足break;}}}if(has_conflict)cout<<"NO"<<endl;// 存在矛盾,不可满足elsecout<<"YES"<<endl;// 无矛盾,可以满足}return0;}

【运行结果】

2 2 1 2 1 1 2 0 NO 2 1 2 1 2 1 1 YES
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/16 5:37:05

Python自动化实战:模拟用户行为找回绑定QQ号

1. 项目概述&#xff1a;当手机号成为找回QQ的钥匙最近在帮一个朋友处理旧账号时&#xff0c;遇到了一个挺典型的问题&#xff1a;他记得自己有好几个QQ号&#xff0c;但只记得当时绑定的手机号&#xff0c;具体的QQ号码早就忘得一干二净了。手动去一个个试&#xff1f;不现实。…

作者头像 李华
网站建设 2026/7/16 5:30:14

C++与Access数据库实战:构建安全登录界面的完整指南

1. 项目概述&#xff1a;为什么用C和Access做登录界面&#xff1f;如果你是一名C开发者&#xff0c;或者正在学习Windows桌面应用开发&#xff0c;那么“用C实现一个Access数据库的登录界面”这个项目&#xff0c;绝对是一个能让你把理论知识串联起来&#xff0c;并且产出实际可…

作者头像 李华
网站建设 2026/7/16 5:30:05

英文分词技术全解析:从基础概念到Transformer实战应用

在自然语言处理的实际应用中&#xff0c;英文分词看似简单却暗藏玄机。很多开发者认为英文天然以空格分隔单词&#xff0c;不需要专门的分词处理&#xff0c;但在处理复合词、缩写、专有名词时常常遇到边界识别问题。本文将系统讲解英文分词的完整技术方案&#xff0c;从基础概…

作者头像 李华
网站建设 2026/7/16 5:28:30

AI编程助手深度集成若依框架:从环境配置到核心模块开发的实战指南

1. 项目概述&#xff1a;当AI助手遇上经典后台框架最近在社区里看到不少朋友在讨论如何利用AI工具来辅助开发&#xff0c;特别是针对像若依&#xff08;RuoYi&#xff09;这样成熟的后台管理系统框架。作为一个常年和各类企业级项目打交道的老码农&#xff0c;我对此深有感触。…

作者头像 李华
网站建设 2026/7/16 5:27:46

C++11 lambda表达式与std::function包装器:现代C++函数式编程核心

1. 项目概述&#xff1a;为什么C11的lambda和包装器是“现代C”的基石如果你是从C98/03时代一路走过来的老码农&#xff0c;看到“lambda表达式”和“包装器”这几个字&#xff0c;大概率会和我一样&#xff0c;有种“终于等到你”的感觉。在C11之前&#xff0c;我们想实现一个…

作者头像 李华
网站建设 2026/7/16 5:26:05

AI产品命名策略与竞品跟踪:从Sam Altman误判Claude事件谈起

1. 先搞清楚这件事到底是怎么回事Sam Altman 在社交媒体上看到有人提到 Claude AI&#xff0c;第一反应是“这名字听起来像在讽刺我”&#xff0c;还专门发帖问“这是认真的还是开玩笑的”。后来才知道 Claude 是 Anthropic 公司开发的真实 AI 产品&#xff0c;和 OpenAI 的 Ch…

作者头像 李华