1 条题解
-
0
解题思路
- 并查集初始化:使用两个大小为 (2N) 的数组
fa
和num
来实现并查集,其中fa
用于存储每个元素的父节点,num
用于记录集合的大小。将每个元素的父节点初始化为自身,对于前 (N) 个表示句子的元素,将其集合大小初始化为 (1) 。这里开 (2N) 大小是为了区分句子的两种状态(假设句子 (i) , (i) 表示句子为真, (i + N) 表示句子为假 )。 - 处理输入并合并集合:逐行读取句子信息,根据句子中判断是“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
为真。
- 当句子为“true.”时,意味着当前句子 (i) 和所指句子 (t) 真假性相同,所以将代表它们为真的集合
- 计算最大真值数量:如果整个过程没有出现矛盾(
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; } }
- 并查集初始化:使用两个大小为 (2N) 的数组
- 1
信息
- ID
- 292
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 14
- 已通过
- 1
- 上传者