题意
n个玩家,m条指令(i说j是imposter/crewmate)要求求出imposter可能最多为多少人
思路
如果A说B为imposter说明2者属于不同团队,如果A说B为crewmate则二者属于一个团队(imposter和crewmate都肯那个),我们只需要判断出可能是一个团队的最多人数。
利用并查集,我们把属于同一团队的权值设置为0,不属于的设置为1
代码
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Endl "\n"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 2e5+5;
const int INF = 0x3f3f3f;
const int mod = 1e9 + 7;
const double pi = acos(-1);
inline ll read(){
ll x = 0, f = 1; char ch; ch = getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
ll n,m,ans;
bool flag;
int t[maxn<<1],size[maxn<<1];
void makeset()
{
for(int i=1;i<=2*n;i++)
t[i]=i;
}
int getf(int x)
{
if(x!=t[x])
t[x]=getf(t[x]);
return t[x];
}
void unionset(int x,int y)
{
int k=getf(x);
int v=getf(y);
cout<<k<<" "<<v<<Endl;
if(k!=v)
{
cout<<size[k]<<" "<<size[v]<<Endl;
t[v]=k;
size[k]+=size[v];
size[v]=0;
}
return ;
}
void solve() {
ans=0,flag=0;
n=read(),m=read();
if(!m)
{
cout<<n<<Endl;
return ;
}
makeset();
for(int i=1;i<=n;i++) size[i]=1;
for(int i=n+1;i<=n*2;i++) size[i]=0;
for(int i=1;i<=m;i++)
{
ll x,y;
string t;
x=read(),y=read();
cin>>t;
if(t[0]=='i')
{
unionset(x,y+n);
unionset(x+n,y);
}
else
{
unionset(x,y);
unionset(x+n,y+n);
}
}
for(int i=1;i<=n;i++)
{
if(getf(i)==getf(i+n))
{
if(!flag)
cout<<"-1"<<Endl;
flag=1;
}
ans+=max(size[i],size[i+n]);
}
if(!flag) cout<<ans<<Endl;
return ;
}
int main() {
for(int T = read(); T; T--)
solve();
return 0;
}