ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

The Number of Imposters 图染色(1700)

2021-11-21 11:02:35  阅读:170  来源: 互联网

标签:1700 连通 ok ve int Number pb Imposters col


在这里插入图片描述
题意 :

  • 现在有n个人,有诚实的人也有撒谎的人,诚实的人只讲真话,撒谎的人只讲谎话,它们共说了m句话,以i j identity的形式给出,代表i认为j是什么身份,如果言语不合法输出-1,否则输出最多的撒谎者个数

思路 :

  • 如果i认为j是诚实的人,则i和j一定类型相同,如果i认为j是撒谎的人,则一定类型不同
  • 我们将类型不同的两人连一条边,类型相同的两人则通过一个fake node进行连边(x-fake node-y)(达到“反反得正”的效果),也因此点的大小要开为n + m
  • 之后对于每一个连通块(整个图可能不连通,所以要把所有没有访问过的点遍历一遍),取其中任意一人,指定其类型为诚实的人,则可以求出整个连通块的类型情况,指定其类型为撒谎的人,也可以求出整个连通块的类型情况,对于这两种方案取最大值(指定其种类为0,在0和1的方案中取最大值)
  • 注意,上面统计每个连通块内两种方案分别最大值后累加到最终结果的过程时,必须是在t[0]和t[1]中取最大值,不能直接n-t[0],因为整个图不一定连通
  • 最终,将所有连通块的方案相加即可,特别地,如果中途推出矛盾(相邻的颜色相同,与“连在一起就是类型不同”相悖),输出-1
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#define endl '\n'
#define pb push_back
 
using namespace std;
 
typedef long long ll;

const int N = 7e5 + 10;

int n, m;
vector<int> ve[N];
int t[2];       // t[0/1]记录连通块内染0/1的数量
bool ok;        // ok记录是否有矛盾情况
int col[N];     // col记录染色情况

void dfs(int now)
{
    for (auto it : ve[now])
    {
        if (col[it] == col[now])
        {
            ok = false;
            return ;
        }
        if (col[it] != -1) continue;
        
        col[it] = 1 - col[now];
        if (it <= n) t[col[it]] ++ ;       // 不是fake node就统计所属颜色个数
        dfs(it);        // 继续遍历当前连通块
    }
}

void solve()
{
    cin >> n >> m;
    
    ok = true;
    for (int i = 1; i <= n + m; i ++ ) col[i] = -1, ve[i].clear(); // 染色,初始设为-1
    
    int cnt = n;
    while (m -- )
    {
        int x, y; string s;
        cin >> x >> y >> s;
        
        if (s[0] == 'i')
        {
            ve[x].pb(y);
            ve[y].pb(x);
        }
        else
        {
            ve[x].pb( ++ cnt);
            ve[cnt].pb(x);
            ve[y].pb(cnt);
            ve[cnt].pb(y);
        }
    }
    
    int ans = 0;
    for (int i = 1; i <= n; i ++ )
    {
        if (col[i] != -1) continue;
        col[i] = 0;
        t[0] = 1, t[1] = 0;

        // 对一个连通块进行染色
        dfs(i);

        ans += max(t[0], t[1]);
    }
    
    if (!ok) ans = -1;
    cout << ans << endl;
}
 
int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    
    int _ = 1;
    cin >> _;
    
    while (_ -- )
    {
        solve();
    }
    
    return 0;
}

标签:1700,连通,ok,ve,int,Number,pb,Imposters,col
来源: https://blog.csdn.net/m0_51448653/article/details/121450157

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有