题目地址:点击打开链接
思路:先贴一下官方题解,
最多搜17条边没太搞懂,感觉是对点深搜才能用到,对边深搜用不到
题意是给了n个人,m个关系,这种关系可以是线上关系,也可以是线下关系(题目只说了是朋友关系,害得我半天才搞明白),然后使每个人的线下和线上关系的人数相同,问有多少种方法,扯点题外话,DFS一般是求可能性,即从这个点走到那个点是否可能,而后求方法的可能性,这样就变成了回溯,搜索的方法我目前知道的只有2种,对点深搜,对边深搜
给一个无向图 , 每条边可以是online边也可以是offline边,问有多少种方法使得每个节点的online边和offline边一样多
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct point
{
int x,y;
}edge[30];
int sum[10],on[10],off[10],n,m,ans;
void dfs(int cur)
{
int i,point1,point2;
if(cur == m)
{
for(i=1; i<=n; i++)
{
if(on[i] != off[i])
break;
}
if(i<=n)
return;
else
ans++;
return;
}
point1 = edge[cur].x;
point2 = edge[cur].y;
if(on[point1] < sum[point1]/2 && on[point2] < sum[point2]/2)//线上朋友没有达到总和的一半,可以继续加
{
on[point1]++;
on[point2]++;
dfs(cur+1);
on[point1]--;
on[point2]--;
}
if(off[point1] < sum[point1]/2 && off[point2] < sum[point2]/2)
{
off[point1]++;
off[point2]++;
dfs(cur+1);
off[point1]--;
off[point2]--;
}
}
int main()
{
int t,i;
scanf("%d",&t);
while(t--)
{
memset(sum,0,sizeof(sum));
memset(on,0,sizeof(on));
memset(off,0,sizeof(off));
ans = 0;
scanf("%d%d",&n,&m);
for(i=0; i<m; i++)
{
scanf("%d%d",&edge[i].x,&edge[i].y);//一条边的2个点
sum[edge[i].x]++;
sum[edge[i].y]++;
}
for(i=1; i<=n; i++)//一个点的边数为奇数直接退出
{
if(sum[i] % 2 != 0)
break;
}
if(i<=n)
printf("0\n");
else
{
dfs(0);
printf("%d\n",ans);
}
}
return 0;
}
大神地址: 点击打开链接