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);
    }
  • 相关阅读:
    tuple 元组及字典dict
    day 49 css属性补充浮动 属性定位 抽屉作业
    day48 选择器(基本、层级 、属性) css属性
    day47 列表 表单 css初识
    day 46 http和html
    day 45索引
    day 44 练习题讲解 多表查询
    day 40 多表查询 子查询
    day39 表之间的关联关系、 补充 表操作总结 where 、group by、
    day38 数据类型 约束条件
  • 原文地址:https://www.cnblogs.com/ruthank/p/9510168.html
Copyright © 2011-2022 走看看