多校第二场 1006 hdu 5305 Friends(爆搜)

题目链接:

点击打开链接

题目大意:

给出n个人,他们是m对朋友,朋友分为在线朋友和不在线朋友,每个人的在线朋友和不在线朋友相同,问方案有多少种

题目分析:

我们可以枚举每条边,然后记录每个点的度,它的在线朋友和离线朋友的数量。

然后暴力搜索就行。

有几个可行性的剪枝。

首先当存在一条边上一个点的度数是0时,那么当前的off[i]==on[i]一定成立,成立的话继续搜

首先当存在一条边上的两个点的度数都是0时,那么当前的两个点i,j的off[i]==on[i] , off[j] == on[j],成立的话继续搜

如果这条边上的两个点的度数都不是0,那么继续搜...

不成立就跳出

代码如下:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#define MAX 50

using namespace std;

int t,n,m;
int d[MAX];
int on[MAX];
int off[MAX];
int u[MAX];
int v[MAX];
int ans;

bool check ( int x ,int y )
{
    if ( !d[x] && !d[y] && on[x] == off[x] && on[y] == off[y] )
        return true;
    if ( !d[x] && d[y] && on[x] == off[x] )
        return true;
    if ( d[x] && !d[y] && on[y] == off[y] )
        return true;
    if ( d[x] && d[y] )
        return true;
    return false;
}

void dfs ( int i = 0 )
{
    if ( i == m )
    {
        ans++;
        return;
    }
    int x = u[i];
    int y = v[i];
    d[x]--;d[y]--;
    on[x]++;on[y]++;
    if ( check ( x , y ))
        dfs ( i+1 );
    on[x]--;on[y]--;
    off[y]++;off[x]++;
    if ( check ( x , y ))
        dfs ( i+1 );
    off[y]--;off[x]--;
    d[x]++;d[y]++;
}

int main ( )
{
    scanf ( "%d" , &t );
    while ( t-- )
    {
        ans = 0;
        scanf ( "%d%d" , &n , &m );
        memset ( d , 0 , sizeof ( d ) );
        memset ( on , 0 , sizeof ( on ));
        memset ( off , 0 , sizeof ( off ));
        for ( int i = 0 ; i < m ; i++ )
        {
            scanf ( "%d%d" , &u[i] , &v[i] );
            d[u[i]]++;
            d[v[i]]++;
        }
        dfs ( );
        printf ( "%d\n" , ans );
    }
}


你可能感兴趣的:(C++,DFS)