zoukankan      html  css  js  c++  java
  • 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;
    }




  • 相关阅读:
    windbg 内核模式调试用户进程
    深发展银行编码器(解剖)
    SIM300常用命令
    tdi驱动 for vista or later
    vm命令行控制 (vmrun)
    WMI事件监控
    Visual C++ 中 #pragma 指示符的使用
    IOCP开发的几个概念
    移动web.config文件时造成的错误,
    提高网站速度|页面优化
  • 原文地址:https://www.cnblogs.com/lightspeedsmallson/p/5173958.html
Copyright © 2011-2022 走看看