牛客网暑期ACM多校训练营(第七场)E Counting 4-Cliques (思维)

链接:https://www.nowcoder.com/acm/contest/145/E
来源:牛客网

You love doing graph theory problems. You’ve recently stumbled upon a classical problem : Count the number of 4-cliques in an undirected graph.

Given an undirected simple graph G, a 4-clique of G is a set of 4 nodes such that all pairs of nodes in this set are directly connected by an edge.

This task would be too easy for you, wouldn’t it? Thus, your task here is to find an undirected simple graph G with exactly k 4-cliques. Can you solve this task?

输入描述:
The first line of input contains a single integer k (1 ≤ k ≤ 106).
输出描述:
On the first line, output two space-separated integers, n, m (1 ≤ n ≤ 75, 1 ≤ m ≤ n * (n - 1) / 2). On the next m lines, output two space-separated integers denoting an edge of the graph u, v (1 ≤ u, v ≤ n), where u and v are the endpoints of the edge.

Your graph must not contain any self-loops or multiple edges between the same pair of nodes. Any graph that has exactly k 4-cliques and satisfies the constraints will be accepted. It can be proven that a solution always exist under the given constraints.
示例1
输入
复制
1
输出
复制
4 6
1 2
1 3
1 4
2 3
2 4
4 3
说明
In the sample, the whole graph is a 4-clique.

题意很简单,就是让你构造一个图,这个图要求有K个4完全图的图。

思路:很容易发现N个点的完全图,有C(n,4)个4-clique,最开始我的想法就是先构造一个最大的完全图T,再往里面加点,假设增加点与T中的点个数为x,则会产生C(x,3)个4-clique,打算采取贪心的策略,每次放入一个点能连接最多的,但发现这样并不对,因为题目限制了75个点,所以在用贪心组合一些数的时候会超过这点。所以我们可以利用背包。或者暴力。
因为最大的差异在于71和70的完全图,二者差了将近60000个4-clique。我们只有利用5个点才可以可以构成[0,60000]中任意一个数。所以这题我们要拿出来5个点进行配对。所以上面一个我们最大只能取70,因为如果我们取71。那么剩下的就是最多只有4个点,存在一些数,四个点无法构成,所以最大只能到70。下面的就暴力枚举点就行了,但是因为pow(70,5)会T ,所以我们用book标记一下,用K - (四个的和),判断这个结果是否能由一个点构成,这样就去掉了一层循环。就可以通过了。

代码如下:

#include

using namespace std;
const int MAX = 80;
const int MAX_N = 1e6+10;
int book[MAX_N];
int C4[MAX],C3[MAX];
class Node{
public:
    int u,v;
    Node();
    Node(int _u,int _v);
};
void init(){
    C4[4] = 1;
    for(int i=5;i<=77;++i){
        C4[i] = C4[i-1]*i/(i-4);
    }
    memset(book,0,sizeof(book));
    C3[3] = 1;
    book[0] = 2;
    book[1] = 3;
    for(int i=4;i<=77;++i){
        C3[i] = C3[i-1]*i/(i-3);
        book[C3[i]] = i;
    }
}
vector vec;
void gouzao(int k){
    for(int i=1;i<=k;++i){
        for(int j=i+1;j<=k;++j){
            vec.push_back(Node(i,j));
        }
    }
}
int main(void){
    init();
    int K,now;
    cin >> K;
    int pos = 0;
    for(int i=3;i<=70;++i)
        if(K >= C4[i])  pos = i;
    gouzao(pos);
    now = pos;
    K -= C4[pos];
    bool ok = true;
    for(int i=1;i<=now&&ok;++i)
    for(int j=1;j<=now&&ok;++j)
    for(int k=1;k<=now&&ok;++k)
    for(int l=1;l<=now&&ok;++l){
        int sum = C3[i]+C3[j]+C3[k]+C3[l];
        int leave = K-sum;
        if(leave >=0 && book[leave] <= now && book[leave] != 0){
            for(int v=1;v<=i;++v)
                vec.push_back(Node(v,now+1));
            for(int v=1;v<=j;++v)
                vec.push_back(Node(v,now+2));
            for(int v=1;v<=k;++v)
                vec.push_back(Node(v,now+3));
            for(int v=1;v<=l;++v)
                vec.push_back(Node(v,now+4));
            for(int v=1;v<=book[leave];++v)
                vec.push_back(Node(v,now+5));
            ok = false;
            now += 5;
        }
    }
    int N = now,M = vec.size();
    printf("%d %d\n",N,M);
    for(int i=0;iprintf("%d %d\n",vec[i].u,vec[i].v);
    }
    return 0;
}
Node::Node(){
    u = v = 0;
}
Node::Node(int _u,int _v){
    u = _u;
    v = _v;
}

你可能感兴趣的:(思维题,牛客网多校)