首页 > 其他分享 >[ABC282D] Make Bipartite 2 题解

[ABC282D] Make Bipartite 2 题解

时间:2022-12-18 13:11:28浏览次数:55  
标签:二分 cnt return int 题解 Make ABC282D dfs color

题目描述

给定一个无向简单图 \(G\),统计有多少个点对 \((u, v)\) 满足:

  • \(u, v\) 之间没有边直接连接:\((u, v) \notin \text E\)
  • 连接 \((u, v)\) 后 \(G\) 是 二分图

一个无向图被称为二分图,当且仅当可以将每个顶点涂成黑色或白色且满足以下条件:

  • 没有边连接以相同颜色的顶点。

思路

什么时候 D题 也开始考图论了

不妨先对原图进行染色

bool dfs(int p, int c)
{
    color[p] = c;
    for (auto i : g[p]) // vector存图
    {
        if (!color[i])
            if (!dfs(i, 3 - c))
                return 0;
        else if (color[i] == c)
            return 0;
    }
    return 1;
}

假如我们得到了这样的图(样例1):

233

此时有两种情况:

  1. 原图不是二分图,输出 0
  2. 如果要进行连边,为了保持原图二分图的特性,只能连接异色两点。

于是答案就是:异色点对的数量

所以我们只需要统计有多少两个异色点就可以了——


\(\huge吗!?\)

如果你这么想就太天真了,看下面这个 \(\texttt{hack}\):

10 1
1 2

微信图片_20221218124523.png

此时你不知道那些孤立的点该如何染色,如果随便染一个颜色的话会漏情况。

如何解决??

反向考虑问题:

最终答案 = 所有情况 - 不可能情况

  1. 所有情况:\(\dfrac{n(n-1)}{2} - m\),所有可能的连边减去已经连上的边。
  2. 不可能情况:\(\dfrac{cnt_1(cnt_1-1)}{2} + \dfrac{cnt_2(cnt_2-1)}{2}\) 两种颜色集合内部连边

这样就自动计算了那些漏掉的情况

码来!

// Problem: D - Make Bipartite 2
// Contest: AtCoder - HHKB Programming Contest 2022 Winter(AtCoder Beginner Contest 282)
// URL: https://atcoder.jp/contests/abc282/tasks/abc282_d
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// Author: Moyou
// Copyright (c) 2022 Moyou All rights reserved.
// Date: 2022-12-17 20:28:38

#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;

const int N = 1e6 + 10;

vector<int> g[N];

int color[N];
int cnt1, cnt2, ans;
bool flg = 1;

bool dfs(int p, int c) // 染色法
{
    color[p] = c;
    if (c == 1)
        cnt1++; // 统计黑白色点的个数
    else
        cnt2++;
    for (auto i : g[p])
        if (!color[i] && !dfs(i, 3 - c) || color[i] == c)
            return 0;
    return 1;
}

int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int a, b;
        cin >> a >> b;
        g[a].push_back(b);
        g[b].push_back(a);
    }

    ans = n * (n - 1) / 2 - m;
    for (int i = 1; i <= n; i++)
    {
        if (color[i] == 0) // 如果未染色,表明这是一个新连通块
        {
            cnt1 = cnt2 = 0;  // 记得重置
            flg &= dfs(i, 1); // 为什么是 &= ?
            // 只要有一个连通块不是二分图,全图就不是二分图
            ans -= (cnt1 - 1) * cnt1 / 2 + (cnt2 - 1) * cnt2 / 2;
        }
    }
    if (!flg)
        puts("0");
    else
        cout << ans << endl;

    return 0;
}

标签:二分,cnt,return,int,题解,Make,ABC282D,dfs,color
From: https://www.cnblogs.com/MoyouSayuki/p/16990223.html

相关文章

  • 「REMAKE C++」Day 3
    Day3完成了C++Primer第4,5章的阅读常量迭代器,不能修改其所指向的对象,可以移动它,vector<int>::const_iteratorit=v.begin();,常量容器只有常量迭代器。标......
  • D - Make Bipartite 2
    D-MakeBipartite2https://atcoder.jp/contests/abc282/tasks/abc282_d SimpleGraphhttps://mathworld.wolfram.com/SimpleGraph.html Asimplegraph,also......
  • 题解 CF1762E【Tree Sum】
    problem根据prufer引理,有标号的无根树的种类是\(n^{n-2}\)。对于一棵n个节点的带权无根树,边权总是+1或者-1。那么总共有\(n^{n-2}*2^{n-1}\)种树。其......
  • 题解 CF1109D【Sasha and Interesting Fact from Graph Theory】
    problem你尤其钟情\(a,b\)这两个数。对于一棵N个节点的树,已知所有边的长度都在\([1,m]\)之间,如果节点\(a\)和\(b\)的距离恰好为\(m\),那么你认为这棵树很好看......
  • 题解 AGC059C【Guessing Permutation for as Long as Possible】
    problem小明有一个隐藏的排列\(p\),小红想要猜出来。现在允许小红提问,每次提问的形式是\(a_i\)和\(b_i\),然后小明会告诉小红谁大谁小。小红是个老实的人,她的询问顺序......
  • 题解 SS221112B【Y】
    problem\(2n\)个有顺序的整数,每个数在\([0,m]\)内随机独立均匀生成,求前一半的和大于后一半的和的方案数。\(T,n,m\leq2000\)。solution0总方案数是明晰的:\(S=(m+1)......
  • 洛谷P3224 [HNOI2012]永无乡 题解 splay tree 启发式合并
    题目链接:https://www.luogu.com.cn/problem/P3224主要知识点是:树上启发式合并,即每次合并将小的树里面的每个点合并大大的树里面,时间复杂度\(O(n\log^2n)\)。同时需要......
  • java跨域问题解决
    问题描述:在使用前后端分离的情况下,前端访问后端时会出现跨域问题解决方式:1.设置跨域1)、单个控制器方法CORS注解在单个方法中加入注解@CrossOrigin。2)、整个控制器......
  • 题解 SP10264 METEORS - Meteors
    整体二分经典题,所以我们用分块解决Solution和整体二分类似,我们把\(k\)次操作分成\(\sqrtk\)块,每一块一起考虑。对于区间加,可以转化为差分,那么在每个块一起作差分后......
  • CodeForces-300#B 题解
    题意给定\(n\)个数,保证\(n\mid3\),要将这\(n\)个数分配到\(\dfrac{n}{3}\)个三元组,有\(m\)个要求\(a,b\),每个要求表示\(a,b\)要在同一个三元组里,求最后的分......