注意审题 只有一个人犯罪
我们不妨先假设所有人都没有犯罪
那么说别人犯罪的人就在说假话 说别人没有犯罪的人就在说真话
并记录每个人被说犯罪了多少次 被说没犯罪多少次
然后遍历每个人 如果他犯了罪 那么说他犯罪的人就是说的真话 说他没犯罪的人就是说的假话 把评论这个人犯罪的那些人反一下 如果这样恰好说真话的人数等于m 那么这个人就是嫌疑犯
注意到输出不止有truth和lie,还有not defined。什么时候是not defined呢?如果有多个嫌疑犯,那么评论这些嫌疑犯的人都是not defined。
本题最坑的一点就是
有些人犯了罪,莫得人说他
这就是为什么会有vis
Talk is cheap, show me the code.
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#define MAXN 100010
using namespace std;
int sum_true, sum_false, cnt, rem[MAXN], rv[MAXN], vis[MAXN];
vector <int> FZ[MAXN], fz;
void Init(int n){
memset(rem, 0, sizeof(rem));
memset(rv, 0, sizeof(rv));
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++) FZ[i].clear(); fz.clear();
sum_false = sum_true = cnt = 0;
}
int main(){
int T, n, m, a;
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
Init(n);
for(int i = 1; i <= n; i++){
scanf("%d", &a);
if(a > 0) {sum_false++; rem[i] = -1;}
else {sum_true++; rem[i] = 1;}
FZ[abs(a)].push_back(i);
rv[abs(a)] += (a > 0) ? 1 : -1;
vis[abs(a)] = 1;
}
for(int i = 1; i <= n; i++){
if(vis[i] && sum_true + rv[i] == m) fz.push_back(i);
if(!vis[i]) cnt++;
}
if(fz.size() > 1){
for (int i = 0; i < fz.size(); i++)
for (int j = 0; j < FZ[fz[i]].size(); j++) rem[FZ[fz[i]][j]] = 0;
}
else if(fz.size() == 1){
if(sum_true == m && cnt) for(int i = 0; i < FZ[fz[0]].size(); i++) rem[FZ[fz[0]][i]] = 0;
else for(int i = 0; i < FZ[fz[0]].size(); i++) rem[FZ[fz[0]][i]] *= -1;
}
for(int i = 1; i <= n; i++) {
if (rem[i] == 0) printf("Not defined\n");
else if (rem[i] == -1) printf("Lie\n");
else printf("Truth\n");
}
}
return 0;
}
8.11更新
需要vis吗???vis搞复杂了
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#define MAXN 100010
using namespace std;
int sum_true, sum_false, rem[MAXN], rv[MAXN];
vector <int> FZ[MAXN], fz;
void Init(int n){
memset(rem, 0, sizeof(rem));
memset(rv, 0, sizeof(rv));
for(int i = 1; i <= n; i++) FZ[i].clear(); fz.clear();
sum_false = sum_true = 0;
}
int main(){
int T, n, m, a;
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
Init(n);
for(int i = 1; i <= n; i++){
scanf("%d", &a);
if(a > 0) {sum_false++; rem[i] = -1;}
else {sum_true++; rem[i] = 1;}
FZ[abs(a)].push_back(i);
rv[abs(a)] += a > 0 ? 1 : -1;
}
for(int i = 1; i <= n; i++)
if(sum_true + rv[i] == m) fz.push_back(i);
if(fz.size() > 1) {
for (int i = 0; i < fz.size(); i++)
for (int j = 0; j < FZ[fz[i]].size(); j++) rem[FZ[fz[i]][j]] = 0;
}
else if(fz.size() == 1) for(int i = 0; i < FZ[fz[0]].size(); i++) rem[FZ[fz[0]][i]] *= -1;
//可能fz.size()==0 所以必须判断if(fz.size() == 1),不能直接用FZ[fz[0]],会RE
for(int i = 1; i <= n; i++) {
if (rem[i] == 0) printf("Not defined\n");
else if (rem[i] == -1) printf("Lie\n");
else printf("Truth\n");
}
}
}