The Number of Imposters

D. The Number of Imposters time limit per test3 seconds memory limit
per test256 megabytes inputstandard input outputstandard output
Theofanis started playing the new online game called “Among them”.
However, he always plays with Cypriot players, and they all have the
same name: “Andreas” (the most common name in Cyprus).

In each game, Theofanis plays with n other players. Since they all
have the same name, they are numbered from 1 to n.

The players write m comments in the chat. A comment has the structure
of “i j c” where i and j are two distinct integers and c is a string
(1≤i,j≤n; i≠j; c is either imposter or crewmate). The comment means
that player i said that player j has the role c.

An imposter always lies, and a crewmate always tells the truth.

Help Theofanis find the maximum possible number of imposters among all
the other Cypriot players, or determine that the comments contradict
each other (see the notes for further explanation).

Note that each player has exactly one role: either imposter or
crewmate.

Input The first line contains a single integer t (1≤t≤104) — the
number of test cases. Description of each test case follows.

The first line of each test case contains two integers n and m
(1≤n≤2⋅105; 0≤m≤5⋅105) — the number of players except Theofanis and
the number of comments.

Each of the next m lines contains a comment made by the players of the
structure “i j c” where i and j are two distinct integers and c is a
string (1≤i,j≤n; i≠j; c is either imposter or crewmate).

There can be multiple comments for the same pair of (i,j).

It is guaranteed that the sum of all n does not exceed 2⋅105 and the
sum of all m does not exceed 5⋅105.

Output For each test case, print one integer — the maximum possible
number of imposters. If the comments contradict each other, print −1.

Example inputCopy 5 3 2 1 2 imposter 2 3 crewmate 5 4 1 3 crewmate 2 5
crewmate 2 4 imposter 3 4 imposter 2 2 1 2 imposter 2 1 crewmate 3 5 1
2 imposter 1 2 imposter 3 2 crewmate 3 2 crewmate 1 3 imposter 5 0
outputCopy 2 4
-1 2 5 Note In the first test case, imposters can be Andreas 2 and 3.

In the second test case, imposters can be Andreas 1, 2, 3 and 5.

In the third test case, comments contradict each other. This is
because player 1 says that player 2 is an imposter, and player 2 says
that player 1 is a crewmate. If player 1 is a crewmate, then he must
be telling the truth, so player 2 must be an imposter. But if player 2
is an imposter then he must be lying, so player 1 can’t be a crewmate.
Contradiction.

commet为crewmate边权为0,亦或后父子节点角色相等
commet为Imposters边权为1, 亦或后父子节点角色相反

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e6+5;
const int mod=1e9+7;
int adj[maxn],nex[maxn],to[maxn],val[maxn];
int role[maxn];
int part[2];
int nums=0;
void merge_(int i,int j,int w)
{
    nex[++nums]=adj[i];
    adj[i]=nums;
    to[nums]=j;
    val[nums]=w;
}
void merge_all(int i,int j,int w)
{
    merge_(i,j,w);
    merge_(j,i,w);
}
bool fns=false;
void dfs(int root,int father)
{
    if(role[root]==-1){
        role[root]=0;
    }
    part[role[root]]++;
    for(int j=adj[root];j;j=nex[j])
    {
        if(father==to[j])continue;
        if(role[to[j]]==-1){
            role[to[j]]=val[j]^role[root];
        dfs(to[j],root);
        }
        else if(role[to[j]]!=val[j]^role[root]){
            fns=true;break;
        }

    }
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int m,n,r,t;
        cin>>m>>n;
        for(int i=1;i<=m;i++){role[i]=-1;adj[i]=0;}
        for(int i=1;i<=2*n;i++)
        {
            nex[i]=to[i]=val[i]=0;
        }
        string str;
        for(int i=1;i<=n;i++)
        {
            cin>>r>>t>>str;
            if(str=="crewmate")
            {
                merge_all(r,t,0);//
            }
            else {
                merge_all(r,t,1);
            }
        }
        int step=0;
        for(int i=1;i<=m;i++)
        {
            part[0]=part[1]=0;
            fns=false;
            if(role[i]==-1)
            dfs(i,0);
            step+=max(part[0],part[1]);
            //两种情况
            if(fns)break;
        }

        if(fns){
            cout<<"-1"<<endl;
        }
        else{
            cout<<step<<endl;
        }

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值