zoukankan      html  css  js  c++  java
  • Kattis

    From : North American Invitational Programming Contest 2018

    给你一个图,以及它的补图。如果部分点在原图中是团,并且其他的所有点在补图中也是团,那么就叫做一个双团。

    要求计算图中双团的数量。

    这篇博客使我理解了这个问题:zro  https://www.cnblogs.com/clrs97/p/8730429.html  orz

    如果其他点在补图中构成团,那么这些点在原图中是一个独立集。

    可以想到,满足条件的状态是 (团的点数) × (团的点数 - 1) + 独立集点的度数和 =  团点的度数和。

    因为 (团的点数) × (团的点数 - 1) = 团中所有边构成的度数,所以剩下的度数就是团的点 与 独立集的点之间的边所构成的度数了。

    这样我们可以找出一种可行方案。

    那么剩下的方案,可能是

    1:团中一个点加入到独立集中:

    2:也可能是独立集中一个点加入到团中

    3:1+2

    分别统计答案即可。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const int maxn = 2*1e5 + 10;
    const LL M = 1e9+7;
    
    int d[maxn], sum[maxn];
    
    
    int main()
    {
            int n, m;
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= m; i++)
            {
                    int x, y;
                    scanf("%d%d", &x, &y);
                    d[x]++, d[y]++;
            }
            sort(d+1, d+1+n);
            reverse(d+1, d+1+n);
    
            for (int i = 1; i <= n; i++)
                    sum[i] = sum[i-1] + d[i];
    
            LL ans = 0;
            int mid = 0;
            for (int i = 0; i <= n; i++)
                    if (1ll*i*(i-1)+sum[n]-sum[i] == sum[i])
                    {
                            ans++;
                            mid = i;
                            break;
                    }
                    
            //找到一种可行方案。
            //团中的点的度数一定大于等于独立集中的点的度数,所以排个序直接枚举断点即可。
    
            if (!ans)
            {
                    printf("0
    ");
                    return 0;
            }
            for (int i = 1; i <= mid; i++)
                    if (1ll*(mid-1)*(mid-2)+sum[n]-sum[mid]+d[i] == sum[mid]-d[i]) ans++;
            for (int i = mid+1; i <= n; i++)
                    if (1ll*(mid+1)*mid+sum[n]-sum[mid]-d[i] == sum[mid]+d[i]) ans++;
    
            LL x = 0, y = 0;
            for (int i = 1; i <=mid; i++)
                    if (d[i] == d[mid]) x++;
            for (int i = mid+1; i <= n; i++)
                    if (d[i] == d[mid]) y++;
    
            ans = (ans+x*y)%M;
            printf("%lld", ans);
    }
  • 相关阅读:
    leecode 240. 搜索二维矩阵 II
    leecode 103. 二叉树的锯齿形层序遍历
    leecode 362. 敲击计数器
    leecode 152. 乘积最大子数组
    leecode 560. 和为K的子数组
    面试题 08.12. 八皇后
    leecode 450. 删除二叉搜索树中的节点
    leecode 384. 打乱数组
    leecoode 138. 复制带随机指针的链表
    mysql基本指令2
  • 原文地址:https://www.cnblogs.com/ruthank/p/9510168.html
Copyright © 2011-2022 走看看