1. 程式人生 > >HDU5952 Counting Cliques (暴力深搜+剪枝) (2016ACM/ICPC亞洲賽區瀋陽站 Problem E)

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