题目大意:

给你一个无向图,100个点1000条边,问你这个图中有多少个小于等于s的点集可以组成一个完全图。s<=10

分析:

其实是想复杂了,真的只需要暴力搜索就可以了。分析复杂度的时候不应该是考虑每个点都有20个出边,所以是10的20次方。而应该是考虑只有1000条边,所以我最多才枚举1000条边,100个点,再加上每次判断最多1e6的时间复杂度,再加一些剪枝,肯定不会超时的。
然后就是如何避免搜索出重复的呢,我的考虑是,用邻接表存边,而且我只存起点标号小于终点标号的边,这样在枚举的过程中我既避免了重复计算,又完成了剪枝。还降低了代码复杂度。

代码:

#include<bits/stdc++.h>
using namespace std;
int con[105][105],ans,n,m,s;
vector<int>a[105];
int now[20];
void dfs(int x)
{
    if(x==s-1)
    {
        ans++;
        return;
    }
    int pre=now[x];
    for(int i=0;i<a[pre].size();i++)
    {
        int flag=1;
        for(int j=0;j<=x;j++)
        {
            if(con[a[pre][i]][now[j]]==0)
            {
                flag=0;break;
            }
        }
        if(flag==1)
        {
            now[x+1]=a[pre][i];
            dfs(x+1);
        }
    }
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(con,0,sizeof(con));
        for(int i=0;i<105;i++)a[i].clear();
        scanf("%d%d%d",&n,&m,&s);
        for(int i=0;i<m;i++)
        {
            int temp_f,temp_t;
            scanf("%d%d",&temp_f,&temp_t);
            con[temp_f][temp_t]=1;
            con[temp_t][temp_f]=1;
            if(temp_t<temp_f){int temp=temp_f;temp_f=temp_t;temp_t=temp;}
            a[temp_f].push_back(temp_t);
        }
        ans=0;
        memset(now,0,sizeof(now));
        for(int i=1;i<=n;i++)
        {
            now[0]=i;
            dfs(0);
        }
        printf("%d\n",ans);
    }
}