HDU 5305 Friends (DFS,穷举+剪枝)
2015-07-23 19:29
387 查看
题意:
给定n个人,m对朋友关系,如果对于每个人,只能刚好选择其所有朋友中的一半的人进行聊天(只是我和我的朋友,不是我的朋友和我的朋友),那么有多少种情况?只要一个选择不同,视为不同情况。
思路:
比如我在14个朋友中选择了7个跟我聊天,那么另外7人已经完全与我没干系,而和我聊天的7个朋友,也已经和我聊天了,即我们配对了,共7对,他所选择的那一半的人中也必须有我。
其实只考虑所给的m条边就行了。如果是奇数对关系,必定有人是奇数个朋友,那么也就0种情况。如果是偶数条边,还得判断每个人是否都是偶数个朋友,若不是也是0种。
满足了情况之后再对m个关系选取其中的m/2条即可。但是所选的关系也必须是满足要求的,那么对于所选的m/2条关系进行判断即可知道是否满足要求,穷举所有可能进行判断。DFS就可以了,每条边要么选,要么不选。但是必须剪枝才能过。
AC代码
给定n个人,m对朋友关系,如果对于每个人,只能刚好选择其所有朋友中的一半的人进行聊天(只是我和我的朋友,不是我的朋友和我的朋友),那么有多少种情况?只要一个选择不同,视为不同情况。
思路:
比如我在14个朋友中选择了7个跟我聊天,那么另外7人已经完全与我没干系,而和我聊天的7个朋友,也已经和我聊天了,即我们配对了,共7对,他所选择的那一半的人中也必须有我。
其实只考虑所给的m条边就行了。如果是奇数对关系,必定有人是奇数个朋友,那么也就0种情况。如果是偶数条边,还得判断每个人是否都是偶数个朋友,若不是也是0种。
满足了情况之后再对m个关系选取其中的m/2条即可。但是所选的关系也必须是满足要求的,那么对于所选的m/2条关系进行判断即可知道是否满足要求,穷举所有可能进行判断。DFS就可以了,每条边要么选,要么不选。但是必须剪枝才能过。
#include <bits/stdc++.h> #define LL long long #define pii pair<int,int> #define INF 0x7f7f7f7f using namespace std; const int N=10; int n, m, s[65], e[65], num, times , du ; int DFS(int x) //x是第几条边 { if( num*2>=m ) //已经够一半了,判断是否满足要求 { for(int i=1; i<=n; i++) if( 2*du[i]!= times[i] ) return 0; //每个人的度有一半即可。 return 1; } int ans=0; if( du[ s[x] ]*2<times[ s[x] ] && du[ e[x] ]*2 <times[e[x]] ) //剪枝:这条边两个端点都已经满度,就不能再选了。 { du[s[x]]++,du[e[x]]++; num++; //所选边的数量 ans+=DFS(x+1); du[s[x]]--,du[e[x]]--; num--; } if( m/2-num < m-x ) //还没有决定是否选的边数必须不小于m的一半 ans+=DFS(x+1); return ans; } int cal(int n ) { //先检查是否满足奇数度的要求 if(m&1) return 0; for(int i=1; i<=n; i++) if( times[i]&1 ) return 0; num=0; memset(du,0,sizeof(du)); return DFS(0); } int main() { //freopen("e://input.txt", "r", stdin); int t; cin>>t; while(t--) { memset(times, 0, sizeof(times)); scanf( "%d%d",&n,&m ); for(int i=0; i<m; i++) { scanf("%d%d",&s[i],&e[i]); times[s[i] ]++; //记录朋友个数 times[e[i] ]++; } printf("%d\n",cal(n)); } return 0; }
AC代码
相关文章推荐
- leetcode 053 —— Maximum Subarray
- HDOJ 1718 Rank(结构体)
- MatLab7安装方法
- [iOS Keychain本地长期键值存储]
- Python的捕虫笔记
- 黑马程序员——第三篇_知识点整理
- Python的捕虫笔记
- leetcode:Palindrome Linked List
- 那些年,我们读过的python!
- HDU 4745——Two Rabbits
- NGUI3.9.0 Scroll View
- Android开源计划-一周开发app
- hdu 1087 Super Jumping! Jumping! Jumping!(最长上升子序列&dp)
- C++中的关键字explict
- 快速排序优化通过中位数优化
- 【java】利用set集合特性去重
- bzoj-4003 城池攻占
- BZOJ 2588 Count on a tree (COT) 是持久的段树
- 社会保障系列1《介绍》
- Linux远程登录Windows桌面