HDU 5952 [DFS]

题目链接:【http://acm.hdu.edu.cn/showproblem.php?pid=5952】

题意:给出一张无向图,然后判断这张图中一共有多少个不同的大小为S的完全图,并且保证每个点的度不大于20。

题解:好吧,比赛的时候想太多了,结果时间刚不住,TTTT。正解其实很简单,就一个DFS。每次建立DFS(u),表示u在的大小为S的完全图个数,为了保证不重复,我们只建立单向边。每层DFS的时候,取一个点,当且仅的这个点与之前的所有点选过的点有边相连(神优化)。总复杂度是100 * 100 * (2 ^ 19) ,但是,应为边很少,所以,复杂度要少很多。

思维僵化啊。

#include<Bits/stdc++.h>
using namespace std;
const int maxn = 105;
int T, N, M, S;
struct Edge
{
    int to, next;
    Edge() {}
    Edge(int to, int next): to(to), next(next) {}
} E[2050];
int head[maxn], tot;
int mp[maxn][maxn], vis[maxn], tmp[maxn];
int ans = 0;
void initEdge()
{
    for(int i = 0; i <= N; i++) head[i] = -1;
    tot = 0;
}
void addEdge(int u, int v)
{
    E[tot] = Edge(v, head[u]);
    head[u] = tot++;
}
void DFS(int u, int pos)
{
    if(pos == S)
    {
        ans++;
        return ;
    }
    for(int k = head[u]; ~k; k = E[k].next)
    {
        int v = E[k].to;
        bool fg = true;
        for(int i = 0; i < pos && fg; i++)
            if(!mp[v][tmp[i]]) fg = false;
        if(fg)
        {
            tmp[pos] = v;
            DFS(v, pos + 1);
        }
    }
    return ;
}
int main ()
{
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d %d %d", &N, &M, &S);
        initEdge();
        for(int i = 1; i <= N; i++)
        {
            vis[i] = 0;
            for(int j = i + 1; j <= N; j++)
                mp[i][j] = mp[j][i] = 0;
        }
        for(int i = 1; i <= M; i++)
        {
            int u, v;
            scanf("%d %d", &u, &v);
            addEdge(u, v);
            mp[u][v] = mp[v][u] = 1;
        }
        if(S == 2)
        {
            printf("%d\n", M);
            continue;
        }
        ans = 0;
        for(int i = 1; i <= N; i++)
        {
            tmp[0] = i;
            DFS(i, 1);
        }

        printf("%d\n", ans);
    }
    return 0;
}

  

posted @ 2017-09-22 21:00  _Mickey  阅读(300)  评论(0编辑  收藏  举报