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