[USACO2013 Jan]Liars and Truth Tellers真假奶牛

题目链接:..并没有找到

题目大意:


题解:

并查集

看清题意!说的是找最多的前K句话,而不是找最多的K句话qwq(不然我就不会做了..orz

句型有两种:

1、x说y是真的,那么x和y同真同假。

2、x说y是假的,那么x和y一真一假。

所以就有两种关系,可近似看成——“同盟”&"敌对"。

于是就是经典的并查集啦。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 1100

int fa[maxn],em[maxn];//fa-同盟的 em-敌对
int ffind(int x)
{
	if (fa[x]!=x) fa[x]=ffind(fa[x]);
	return fa[x];
}
int main()
{
	//freopen("truth.in","r",stdin);
	//freopen("truth.out","w",stdout);
	int n,m,x,y,i,bk=-1;char c;
	scanf("%d%d",&n,&m);
	for (i=1;i<=n;i++) {fa[i]=i;em[i]=-1;}
	// memset(pd,-1,sizeof(pd));
	for (i=1;i<=m;i++)
	{
		scanf("%d%d %c",&x,&y,&c);
		if (bk!=-1) continue;
		if (c=='T')
		{
			int fx=ffind(fa[x]),fy=ffind(fa[y]);
			if (em[fx]==-1 || em[fy]==-1)//朋友的敌人是敌人
			{
				fa[fy]=fx;
				if (em[fx]!=-1) em[fy]=em[fx];
				else if (em[fy]!=-1) em[fx]=em[fy];
			}else
			{
				int ex=ffind(em[fx]),ey=ffind(em[fy]);
				if (fx==ey || fy==ex) {bk=i;continue;}//有矛盾啦
				fa[fy]=fx;fa[ex]=ey;				
			}
		}else if (c=='L')
		{
			int fx=ffind(fa[x]),fy=ffind(fa[y]);
			if (fx==fy) {bk=i;continue;}//有矛盾啦
			if (em[fx]==-1 || em[fy]==-1)
			{
				if (em[fx]!=-1) {em[fy]=fx;fa[fy]=em[fx];}//敌人的敌人是朋友
				else if (em[fy]!=-1) {em[fx]=fy;fa[fx]=em[fy];}
				else em[fx]=fy,em[fy]=fx;
			}else
			{
				int ex=ffind(em[fx]),ey=ffind(em[fy]);
				fa[fx]=ey;fa[fy]=ex;
			}
		}
	}
	if (bk==-1) bk=m;else bk--;
	printf("%d
",bk);
	return 0;
}


原文地址:https://www.cnblogs.com/Euryale-Rose/p/6527840.html