dfs指定大小的完全图

Posted nonames

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dfs指定大小的完全图相关的知识,希望对你有一定的参考价值。

题意:给你一个无向完全图,求指定大小s个点的完全图子图的个数。

解法:单向建边顺序遍历,避免重复。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<queue>
#include<algorithm>
#include<iostream>
#include<map>
#define inf 0x3f3f3f3f
#define ll long long
#define maxx 5000000
#define mod 2147493647//注意这是一个ll型的数,会爆int
using namespace std;
int vis[109][109];
int temp[109];
int n , m , s ;
int ans , flag;
int head[109];

struct node{
    int to , next ;
}g[2009];
int cnt;

void add(int u , int v)
{
    g[cnt].to = v ;
    g[cnt].next = head[u];
    head[u] = cnt++ ;
}

void dfs(int u , int num)
{
    if(num == s)//如果符合条件的点数等于指定点数,计数。
    {
        ans++;
        return ;
    }
    temp[num] = u ;//将该点加入集合
    for(int i = head[u] ; i != -1 ; i = g[i].next)//dfs0遍历
    {
        int v = g[i].to ;
        flag = 1 ;
        for(int j = 1 ; j < num ; j++)//判断该点是否与已经加入集合的点构成完全图
        {
            if(!vis[v][temp[j]])//与集合内的点不能构成完全图
            {
                flag = 0 ;
                break;
            }
        }
        if(flag)//能构成完全图
        {
            dfs(v , num+1);//加入该点,进入下一个点
        }
    }
}
void init()
{
    memset(head , -1 , sizeof(head));
    cnt = 0 ;
    ans = 0 ;
    memset(vis , 0 , sizeof(vis));
}

int main()
{
    int t ;
    scanf("%d" , &t);
    while(t--)
    {
        init();
        scanf("%d%d%d" , &n , &m , &s);
        for(int i = 0 ; i < m ; i++)
        {
            int  u , v ;
            scanf("%d%d" , &u , &v);
            if(u > v) swap(u , v);//单向顺序
            add(u , v);
            vis[u][v] = vis[v][u] = 1 ;//两点有边相连
        }
        for(int i = 1 ; i <= n ; i++)//遍历每一个点
        {
            dfs(i , 1);
        }
        cout << ans << endl;
    }


    return 0 ;
}

以上是关于dfs指定大小的完全图的主要内容,如果未能解决你的问题,请参考以下文章

CF #405 (Div. 2) B. Bear ad Friendship Condition (dfs+完全图)

HDU5952 dfs+剪枝

hdu5952 Counting Cliques 技巧dfs

P2819 图的m着色问题(DFS)

BZOJ 1815: [Shoi2006]color 有色图 [Polya DFS 重复合并]

HDU 5952