传送门

给N个点,M条边,问有多少个包含S个点的集合,集合中的点两两直接相连。

思路:直接暴力dfs,用一个数组表示当前集合里的点,如果当前枚举的点与这些点都有边,就可以加进去进入下一层dfs,直到枚举的size==S。

为了防止重复,在加边时统一由编号小的点指向编号大的点。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <vector>
#include <set>

using namespace std;

const int MAXN=110;
vector<int> G[MAXN];
int mp[MAXN][MAXN];
int n,m,s;
int T;
int ans;

void dfs(int u,int * tmp, int size)
{
    if (size==s)
    {
        ans++;
        return;
    }
    bool f;
    for(int i=0; i<G[u].size(); i++)//可能加入团的点
    {
        int v=G[u][i];
        f=true;
        for(int j=1; j<=size; j++)//遍历团中所有点,判断是否与将要加入的点相连
        {
            if (!mp[v][tmp[j]])
            {
                f=false;
                break;
            }
        }
        if (f)//这个点可以加入团,加入并继续深搜
        {
            size++;
            tmp[size]=v;
            dfs(v,tmp,size);
            tmp[size]=0;
            size--;
        }
    }
}

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&s);
        for(int i=1; i<=n; i++) G[i].clear();
        memset(mp,0,sizeof(mp));
        ans=0;
        while(m--)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            if (u>v) swap(u,v);
            G[u].push_back(v);
            mp[u][v]=mp[v][u]=1;
        }
        for(int i=1; i<=n; i++)
        {
            int size=1;//团的规模
            int tmp[MAXN];//tmp集合表示这个团中有哪些点 
            tmp[1]=i;
            dfs(i,tmp,size);
        }
        printf("%d\n",ans);
    }
    return 0;
}
Latest posts by 青鸟千秋 (see all)

CF-1025D Recovering BST(区间dp)

传送门 题意:给定n个整数,问是否能生成一棵BST(二分查找树,左子树都比它小,右子树都比它大),并且有边相连的点权的gcd>1。 思路:区间dp,dp[l][...

阅读全文

牛客网暑期多校第五场E room(费用流)

传送门 题意:有n个宿舍,每个宿舍住4个人,给定去年n个宿舍的人员构成,今年n个4人组合的情况,求最少几个人需要搬寝室。 思路:转化为最小费用最大流解...

阅读全文

HDU-4091 Zombie’s Treasure Chest(暴力)

传送门 题意:有一个容量为n的箱子,和无限多的两种珠宝,体积和价值分别是s1,v1,s2,v2,求能装下的最大价值。 思路:直接暴力枚举会TLE,先计算s1 s2的LC...

阅读全文

欢迎留言