• 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);
    }
  • 相关阅读:
    leetcode 1 两数之和
    leetcode 486 预测赢家
    leetcode 121 买卖股票的最佳时机
    leetcode 5 最长回文子串
    个人作业——软件工程实践总结作业
    个人作业——软件产品案例分析
    软件工程实践2017 个人技术博客
    软件工程实践2017结对项目——第二次作业
    软件工程实践2017结对项目——第一次作业
    课堂笔记(六)
  • 原文地址:https://www.cnblogs.com/ruthank/p/9510168.html
Copyright © 2020-2023  润新知