DFS训练~Friends~解题报告

Friends

题目描述:

There are n people and m pairs of friends. For every pair of friends, they can choose to become online friends (communicating using online applications) or offline friends (mostly using face-to-face communication). However, everyone in these n people wants to have the same number of online and offline friends (i.e. If one person has x onine friends, he or she must have x offline friends too, but different people can have different number of online or offline friends). Please determine how many ways there are to satisfy their requirements.

Input:

The first line of the input is a single integer T (T=100), indicating the number of testcases.

For each testcase, the first line contains two integers n (1≤n≤8) and m (0≤m≤n(n−1)2), indicating the number of people and the number of pairs of friends, respectively. Each of the next m lines contains two numbers x and y, which mean x and y are friends. It is guaranteed that x≠y and every friend relationship will appear at most once.

Output:

For each testcase, print one number indicating the answer.

Sample Input:

在这里插入图片描述

Sample Output:

在这里插入图片描述

题目大意:

给出了T个测试样例子,给了n个人,m对朋友,他要求每一个人都拥有同等数量的在线朋友与离线朋友,要求在m对朋友来分配,有多少种方式,意思就是说这里有m对朋友,但他们没有标明是在线还是离线,所以由你来标明,分配即可。

思路分析:

这道题首先要看每个人拥有多少个朋友,如果该朋友数量是奇数,说明无法同等分配,如果是偶数才能继续分配,这里有个很简单的思路把,就是朋友的数量是固定的,但分配朋友对的数量的时候,在线朋友对多一个,离线朋友对就少一个,那么依次为条件DFS,看是否所有朋友对数量,能否等于m就即可,就多出一种方法。

AC代码:

用时:15ms

#include<cstdio>
#include<iostream>
#include<string.h>
using namespace std;
int num[10000];//记录该人有多少朋友 
int Leave[10000];//在线人数 
int rise[10000];//离线人数 
int sum,flag;//flag用于标记,sum用于方法 
int m,n;
struct 
{
	int n1,n2;
}Lemon[10000];//标记朋友对数量 
void LemonDFS(int num1)
{
	if(num1 == m+1)//如果刚好等于朋友对数量,说明满足条件 
	{
		sum++;
		return;	
	}
	//记录朋友对的关系 
	int LF= Lemon[num1].n1;
	int RF= Lemon[num1].n2;
	if(rise[LF] && rise[RF])//在线人数分配 
	{
		rise[LF]--;
		rise[RF]--;
		LemonDFS(num1+1);
		rise[LF]++;
		rise[RF]++;
	}
	if(Leave[LF] && Leave[RF])//离线人数分配 
	{
		Leave[LF]--;
		Leave[RF]--;
		LemonDFS(num1+1);
		Leave[LF]++;
		Leave[RF]++;
	}
	return;
}
int main()
{
	int T;
	cin >> T;
	while(T--)
	{
		memset(Lemon,0,sizeof(Lemon));
		memset(Leave,0,sizeof(Leave));
		memset(rise,0,sizeof(rise));
		memset(num,0,sizeof(num));
		//刷新4个数组的数据 
		sum=0;//记录 方法数量 
		cin >> n >> m;//输入人数量与朋友数量 
		for(int i=1;i<=m;i++)//开始标明第几号人有多少个朋友 
		{
			cin >> Lemon[i].n1 >> Lemon[i].n2;
			num[Lemon[i].n1]++;
			num[Lemon[i].n2]++;
		}
		flag=0;//标记是否有方法 
		for(int i=1;i<=n;i++)
		{
			rise[i]=Leave[i]=num[i]/2;//如果朋友对是偶数才能同等分配,如果是奇数
			//不满足条件,退出循环。 
			if(num[i]%2!=0)
			{
				flag=1;
				break;
			}
			
		}
		if(flag)//无方法的时候 
		{
			printf("0\n");
		}
		else//有方法的时候就 DFS分配 
		{
			LemonDFS(1);
			printf("%d\n",sum);
	}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值