1 条题解

  • 0
    @ 2025-5-7 11:43:28

    解题思路

    1. 并查集初始化:使用两个大小为 (2N) 的数组 fanum 来实现并查集,其中 fa 用于存储每个元素的父节点,num 用于记录集合的大小。将每个元素的父节点初始化为自身,对于前 (N) 个表示句子的元素,将其集合大小初始化为 (1) 。这里开 (2N) 大小是为了区分句子的两种状态(假设句子 (i) , (i) 表示句子为真, (i + N) 表示句子为假 )。
    2. 处理输入并合并集合:逐行读取句子信息,根据句子中判断是“true.”还是“false.”进行不同操作。
      • 当句子为“true.”时,意味着当前句子 (i) 和所指句子 (t) 真假性相同,所以将代表它们为真的集合 find(i)find(t) 合并,同时将代表它们为假的集合 find(i + N)find(t + N) 合并。如果发现代表真假的两个集合已经被合并过(即 find(i)find(t + N) 或者 find(i + N)find(t) 属于同一集合 ),说明出现矛盾,标记 invalid 为真。
      • 当句子为“false.”时,说明当前句子 (i) 和所指句子 (t) 真假性相反,所以将代表 (i) 为假的集合 find(i + N) 和代表 (t) 为真的集合 find(t) 合并,将代表 (i) 为真的集合 find(i) 和代表 (t) 为假的集合 find(t + N) 合并。若发现代表相同真假性的两个集合已经被合并过(即 find(i)find(t) 属于同一集合 ),则标记 invalid 为真。
    3. 计算最大真值数量:如果整个过程没有出现矛盾(invalid 为假 ),遍历前 (N) 个句子对应的集合,对于每个未访问过的集合 find(i) ,找到其对应的相反状态集合 find(i + N) ,取这两个集合大小的最大值累加到结果 res 中,并标记这两个集合已访问,最后输出 res ,即可以为真的句子的最大数量。
    
    #include<iostream>
    #include <cstring>
    #include<string>
    using namespace std;
    
    int fa[2002],num[2002],N;
    bool visit[1001];
    
    int find(int x){
        if(fa[x]==x)
                    return x;
        return fa[x] = find(fa[x]);
    }
    
    void Union(int x, int y){
         int m = find(x), n = find(y);
         if(m<n)
                fa[n] = m, num[m]+=num[n];
         else if(m>n)
              fa[m] = n, num[n] += num[m];
    }
    
    int main(){
        while(cin>>N&&N){
                      for(int i = 1; i <= 2*N; i++)
                              fa[i] = i, num[i] = 0;
                      for(int i = 1; i <= N; i++)
                              num[i] = 1;
                      
                      bool invalid = 0;
                      string s;
                      int t;
                      for(int i = 1; i <= N; i++){
                              cin >> s;
                              cin >> t;
                              cin >> s;
                              cin >> s;
                              if(s=="true."){
                                             int m = find(i), n = find(t);
                                             if(m-n==N||n-m==N){
                                                                invalid = 1;
                                             }
                                             Union(m,n);
                                             Union(m+N,n+N);
                              }
                              else{
                                   int m = find(i), n = find(t);
                                   if(m==n){
                                            invalid = 1;
                                   }
                                   Union(m+N,n);
                                   Union(m,n+N);
                              }
                      }
                      if(invalid){
                                  cout <<"Inconsistent" << endl;
                                  continue;
                      }
                      memset(visit,0,sizeof(visit));
                      int res = 0;
                      for(int i = 1; i <= N; i++){
                              int m = find(i);
                              if(visit[m]==0){
                                              int n = find(i+N);
                                              //cout << i << " " << fa[i] << " " << num[m] << " " << n << " " << num[n] << endl;
                                              res += max(num[m],num[n]);
                                              visit[m] = visit[n] = 1;
                              }
                      }
                      cout << res << endl;
        }
                      
    }
    
    • 1

    信息

    ID
    292
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    14
    已通过
    1
    上传者