HDU5952 Counting Cliques (暴力深搜+剪枝) (2016ACM/ICPC亚洲赛区沈阳站 Problem E)

题目链接:传送门

题目:

Counting Cliques
Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 4879    Accepted Submission(s): 1747


Problem Description
A clique is a complete graph, in which there is an edge between every pair of the vertices. Given a graph with N vertices and M edges, your task is to count the number of cliques with a specific size S in the graph.
 

Input
The first line is the number of test cases. For each test case, the first line contains 3 integers N,M and S (N ≤ 100,M ≤ 1000,2 ≤ S ≤ 10), each of the following M lines contains 2 integers u and v (1 ≤ u < v ≤ N), which means there is an edge between vertices u and v. It is guaranteed that the maximum degree of the vertices is no larger than 20.
 

Output
For each test case, output the number of cliques with size S in the graph.
 

Sample Input

3
4 3 2
1 2
2 3
3 4
5 9 3
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5
6 15 4
1 2
1 3
1 4
1 5
1 6
2 3
2 4
2 5
2 6
3 4
3 5
3 6
4 5
4 6
5 6

 

Sample Output

3
7
15
View Code

题目大意:

  给定一个有N个点,M条边的图,求有S个点的完全子图的数量。

  (N ≤ 100,M ≤ 1000,2 ≤ S ≤ 10)

思路:

  一个个点加入完全子图,大小达到S时ans++。

  纯暴力好像会在4000ms上下徘徊,随便剪一下就过了。

代码:

#include <bits/stdc++.h>

using namespace std;
const int MAX_N = 1e2 + 5;
const int MAX_M = 1e3 + 5;

int N, M, S;
int ans;
bool edge[MAX_N][MAX_N];
vector <int> Edge[MAX_N];
int vis[MAX_N];

int read() {
    int res = 0;
    char ch = getchar();
    while (!isdigit(ch)) ch = getchar();
    while (isdigit(ch)) {
        res *= 10;
        res += ch - '0';
        ch = getchar();
    }
    return res;
}

void dfs(int dep, int u)
{
    if (Edge[u].size() < S-1)
        return;
    if (S-dep + u > N)
        return;
    if (dep == S) {
        ans++;
        return;
    }

    int Elen = Edge[u].size();
    for (int i = 0; i < Elen; i++) {
        int v = Edge[u][i];
        if (v < u)
            continue;
        if (Edge[v].size() < dep)
            continue;
        bool ok = true;
        for (int j = 1; j <= dep; j++){
            int w = vis[j];
            if (!edge[v][w]) {
                ok = false;
                break;
            }
        }

        if (ok) {
            vis[dep+1] = v;
            dfs(dep+1, v);
        }
    }
}

void addEdge(int u, int v) {
    edge[u][v] = edge[v][u] = true;
    Edge[u].push_back(v);
    Edge[v].push_back(u);
}

int main()
{
    int T;
    cin >> T;
    while (T--) {
        N = read();
        M = read();
        S = read();
        for (int i = 1; i <= N; i++) {
            Edge[i].clear();
            for (int j = 1; j <= N; j++)
                edge[i][j] = false;
        }
        int u, v;
        for (int i = 1; i <= M; i++) {
            u = read();
            v = read();
            addEdge(u, v);
        }
        ans = 0;
        for (int i = 1; i <= N; i++) {
            vis[1] = i;
            dfs(1, i);
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Lubixiaosi-Zhaocao/p/9947393.html