zoukankan      html  css  js  c++  java
  • hdu 5952 Counting Cliques 求图中指定大小的团的个数 暴搜

    题目链接

    题意

    给定一个(n个点,m条边)的无向图,找出其中大小为(s)的完全图个数((nleq 100,mleq 1000,sleq 10))

    思路

    暴搜。

    搜索的时候判断要加进来的点是否与当前集合中的每个点之间都有边。搜到集合大小为(s)就答案+1.

    注意

    如果不做处理的话,每个完全图都会被搜到(2^s)次,其中只有一次是必要的。

    因此,一个很显然的常用的考虑是:搜索的时候下一个节点比当前的节点编号大,这样就肯定不会搜重复了。

    再稍微转化一下,在建图的时候就可以只建小点指向大点的边。

    Code

    #include <bits/stdc++.h>
    #define maxn 110
    #define maxm 1010
    using namespace std;
    typedef long long LL;
    bool mp[maxn][maxn];
    int st[12], ecnt, s, ne[maxn];
    LL ans;
    struct Edge {
        int to, ne;
        Edge(int _to=0, int _ne=0) : to(_to), ne(_ne) {}
    }edge[maxm];
    bool add(int u, int v) {
        edge[ecnt] = Edge(v, ne[u]);
        ne[u] = ecnt++;
    }
    bool check(int v, int tot) {
        for (int i = 0;i <= tot; ++i) {
            if (!mp[st[i]][v]) return false;
        }
        return true;
    }
    void dfs(int tot, int u) {
        st[tot] = u;
        if (tot == s-1) { ++ans, --tot; return; }
        for (int i = ne[u]; ~i; i = edge[i].ne) {
            int v = edge[i].to;
            if (check(v, tot)) dfs(tot+1, v);
        }
    }
    void work() {
        int n, m;
        scanf("%d%d%d", &n, &m, &s);
        memset(mp, 0, sizeof(mp));
        ecnt = 0; memset(ne, -1, sizeof(ne));
        for (int i = 0; i < m; ++i) {
            int x, y;
            scanf("%d%d", &x, &y);
            if (x > y) swap(x, y);
            mp[x][y] = 1; add(x, y);
        }
        ans = 0;
        for (int i = 1; i <= n; ++i) dfs(0, i);
        printf("%lld
    ", ans);
    }
    int main() {
        int T;
        scanf("%d", &T);
        while (T--) work();
        return 0;
    }
    
    
  • 相关阅读:
    iOS 学习
    iOS 学习
    textField和textView限制输入条件
    FMDB的使用
    Xcode7以后 使用空模板
    MJPhotoBrowser BUG修复
    获得通讯录的访问权
    正则运算校验手机号码
    项目中生产模式和开发模式的切换
    自定义的进度条
  • 原文地址:https://www.cnblogs.com/kkkkahlua/p/7704245.html
Copyright © 2011-2022 走看看