CF993B 公开交流
大家春节快乐!
1 CF993B 公开交流
2 题目描述
时间限制 \(1s\) | 空间限制 \(256M\)
有两个人各有一对由数字 \(1\) 到 \(9\) 构成的数对,他们两人数对中都有且只有一个相同的数字。他们两人把自己的数对隐藏在很多数对中,然后在公开的信道中传输。每个数对中的数字都不同。请确定你是否可以从公共信道中的数对推导出这个相同的数字,或者确定他们互相知道了对方的数字,但是你无法推导出来。也有可能他们互相也不知道对方的数字。
3 题解
我们分析什么情况下我们可以确定,什么情况下我们输出 \(0\),什么情况下我们输出 \(-1\)。如果两个数列中只存在一个数相等且处于两个数列中,那么这个数肯定是他们公共的数。如果存在多个相等的数,且某一对数中有两个数都跟对面数列有相同的数,那么即使是这两个人也不知道,输出 \(-1\)。
我们讲讲具体细节:对于输入的所有数对,使用 \(bool\) 类型的两个数组存储,\(f_{a, b} = 1\) 表示存在该数对,\(f_{a, b} = 0\) 表示不存在该数对。随后,我们从 \(1\) 到 \(9\) 枚举公共数字 \(i\),然后再分别枚举第一个数列中与该公共数字可能存在数对的数字 \(j\) 和第二个数列中与该公共数字可能存在数对的数字 \(k\)。如果此时存在数对 \((i, j)\) 和 \((i, k)\),那么我们将答案记为 \(i\),并且给 \(ans_{1, i, j}\) 和 \(ans_{2, i, k}\) 的值设为 \(1\),\(ans_{i, j, k}\) 标志该数对在 \(i\) 数列中以 \(j\) 为公共数字,可以在另外一个数列中找到与其匹配的数。如果我们发现此前已经出现过了某个与 \(i\) 不一样的公共数字,说明我们已经无法确定答案了,将 \(flag\) 置 \(1\)。如果循环结束时 \(flag\) 仍然为 \(0\),那么说明该公共数字唯一,输出即可。
接下来,我们对 \(flag\) 为 \(1\) 的情况进行处理。如果这个时候发现对于任意不相等的 \(j, k\),存在 \(ans_{i, j, k}\) 与 \(ans_{i, k, j}\) 都为 \(1\),也就是说数对 \((j, k)\) 中的 \(j, k\) 都可以在同一个与当前数列不同的数列中找到,此时答案为 \(-1\)。
如果枚举一遍所有的 \(j, k\) 都没有发现上述情况,输出 \(0\)。
4 代码(空格警告):
#include <iostream>
using namespace std;
int n, m, a, b, ans, flag;
bool f1[15][15], f2[15][15];
bool ans1[15][15], ans2[15][15];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a >> b;
f1[a][b] = 1;
f1[b][a] = 1;
}
for (int i = 1; i <= m; i++)
{
cin >> a >> b;
f2[a][b] = 1;
f2[b][a] = 1;
}
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= 9; j++)
{
if (i == j) continue;
for (int k = 1; k <= 9; k++)
{
if (i == k || j == k) continue;
if (f1[i][j] && f2[i][k])
{
if (ans && ans != i) flag = 1;
ans = i;
ans1[i][j] = 1;
ans2[i][k] = 1;
}
}
}
}
if (!flag) cout << ans;
else
{
ans = 0;
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= 9; j++)
{
if (i == j) continue;
if ((ans1[i][j] && ans1[j][i]) || ans2[i][j] && ans2[j][i])
{
ans = -1;
}
}
}
cout << ans;
}
return 0;
}