Zenefits CodeSprint:Knight or Knave


题意是一堆人,从1到n编号,每个人i说一句话,x。x是正数表示i说x君是个好人,x是负数表示i说x君是坏人。问这个群体中最多能有多少好人,把这种情况用字典序的方式输出(好人用A表示,坏人用B表示),希望我把题意说清楚了。

又做了一道Hackerrank上一道很好玩的题目,做的时候怎么都想不出来。。。

但看完了题解之后,又发现这个题目。。。

其实这个思路以前做并查集的时候有过,就是每个人就两种可能,即每个点就两种状态,那就对每个点再增加一个点,i增加一个点,i+n。这两个点始终都是对立的关系,如果i是好人,那么i+n一定是坏人。当时也想到dfs了,就是想把这个类的人归到一起去,比方说i是好人,i说j是好人,j说k是好人,那么就会希望i、j、k搞到一起去。这个时候就发挥了增加这个点的作用了,i比如是好人,i说j是坏人,那这个意思也就是i说j+n是坏人,i和j+n要搞到一起去,我靠,和并查集的一些题一样啊。。。。

后面就是查各个集的人数,胜利即是正义,人多即是正义。

官方题解代码:

#pragma warning(disable:4996)  
#include <iostream>  
#include <algorithm>  
#include <cmath>  
#include <vector>  
#include <string>  
#include <cstring>  
using namespace std;

const int mx = 300003;
int n;

int norma(int x)
{
	if (x < 0)
		return abs(x) + n;
	else
		return x;
}

int inv(int x)
{
	x = norma(x);
	if (x > n)
		return x - n;
	else
		return x + n;
}

vector<int>g[2 * mx];
int kc[mx];
int color[mx];
int flag[mx];

void call(int u, int mar)
{
	if (color[u])
		return;
	color[u] = mar;
	if (u <= n)
		kc[mar]++;
	for (int i = 0; i < g[u].size(); i++)
	{
		int v = g[u][i];
		call(v, mar);
	}
}

void addedge(int u, int v)
{
	g[u].push_back(v);
}

int main()
{
	//freopen("i.txt", "r", stdin);
	//freopen("o.txt", "w", stdout);
	
	int t, u, v, ass;
	int invu, invt;
	cin >> t;
	
	while (t--)
	{
		memset(kc, 0, sizeof(kc));
		memset(color, 0, sizeof(color));
		
		cin >> n;
		for (int i = 1; i <= 2 * n + 1; i++)
		{
			g[i].clear();
		}
		for (int i = 1; i <= n; i++)
		{
			u = i;
			
			cin >> v;
			v = norma(v);

			addedge(u, v);
			addedge(v, u);
			
			invu = inv(u);
			invt = inv(v);

			addedge(inv(u), inv(v));
			addedge(inv(v), inv(u));
		}
		ass = 0;
		for (int i = 1; i <= n * 2; i++)
		{
			if (!color[i])
			{
				ass++;
				call(i, ass);
			}
		}
		memset(flag, 0, sizeof(flag));
		for (int i = 1; i <= n; i++)
		{
			u = i;
			v = inv(i);
			
			u = color[u];
			v = color[v];

			if (!flag[u] && !flag[v])
			{
				if (kc[u] >= kc[v])//查数量,贪心,数量多的为好人
				{
					flag[u] = 1;
					flag[v] = 2;
				}
				else
				{
					flag[u] = 2;
					flag[v] = 1;
				}
			}
		}

		for (int i = 1; i <= n; i++)
		{
			if (flag[color[i]] == 1)
				cout << "A";
			else
				cout << "B";
		}
		cout << endl;
	}
	//system("pause");
	return 0;
}




原文地址:https://www.cnblogs.com/lightspeedsmallson/p/5173958.html