题目链接:
http://acm.fzu.edu.cn/problem.php?pid=2202
思路:
逻辑推理题。
对于每个人i,如果他被指控,则a[i]++;
如果他被澄清,则b[i]++;
然后统计总人数中,澄清的语句的条数s。
那么对于i来说,如果i是罪犯,那么真话数x=a[i]+s-b[i]。
那么我们就可以判断出这个人是否是嫌疑犯了。依据这个我们可以知道哪些人是嫌疑犯。
如果已经确定的嫌疑犯只有一个,那么这个人就是罪犯了,这样所有人说的话是真是假就很容易知道了。
如果已经确定的嫌疑犯有多个,对每一个人i说得话h[i]进行判断:
如果h[i]是正数,那么就看h[i]是否是嫌疑犯,如果是则i说的话难以确定,否则表明i说的是假话。
如果h[i]是负数,那么就看h[i]是否是嫌疑犯,如果不是则i说的难以确定,否则表明i说的是真话。
代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int vis[120005],p[120005],a[120005],b[120005],x[120005];
int main()
{
int T,i,j,k,n,m,s1,s2;
scanf("%d",&T);
while(T--)
{
memset(vis,0,sizeof(vis));
memset(p,0,sizeof(p));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(x,0,sizeof(x));
s1=s2=0;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
cin>>x[i];
if(x[i]>0){a[x[i]]++;s1++;}
else if(x[i]<0){b[-x[i]]++;s2++;}
}
int t=0;
for(i=1;i<=n;i++)
{
int s=a[i]+s2-b[i];
if(s==m){vis[i]=1;t++;}
}
if(t==1)
{
for(i=1;i<=n;i++)
{
if(x[i]>0)
{
if(vis[x[i]])printf("Truth\n");
else printf("Lie\n");
}
else if(x[i]<0){
if(vis[-x[i]])printf("Lie\n");
else printf("Truth\n");
}
}
}
else
{
for(i=1;i<=n;i++)
{
int y=x[i];
if(y>0){
if(vis[y])p[i]=2;
else p[i]=3;
}
if(y<0)
{
if(vis[-y])p[i]=2;
else p[i]=1;
}
}
for(i=1;i<=n;i++)
{
if(p[i]==1)printf("Truth\n");
else if(p[i]==2)printf("Not defined\n");
else if(p[i]==3)printf("Lie\n");
}
}
}
return 0;
}