题目链接:
题目大意:
给出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 );
}
}