51nod 1806 wangyurzee的树(prufer编码求生成树的个数)
来源:互联网 发布:淘宝分享有赏红包在哪 编辑:程序博客网 时间:2024/06/01 07:27
1806 wangyurzee的树
基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 关注
wangyurzee有n个各不相同的节点,编号从1到n。wangyurzee想在它们之间连n-1条边,从而使它们成为一棵树。
可是wangyurzee发现方案数太多了,于是他又给出了m个限制条件,其中第i个限制条件限制了编号为u[i]的节点的度数不能为d[i]。
一个节点的度数,就是指和该节点相关联的边的条数。
这样一来,方案数就减少了,问题也就变得容易了,现在请你告诉wangyurzee连边的方案总数为多少。
答案请对1000000007取模。
样例解释
总方案共有3种,分别为{(1,2),(1,3)},{(1,2),(2,3)},{(2,3),(1,3)}。其中第二种方案节点1的度数为2,不符合要求,因此答案为2。
Input
第一行输入2个整数n(1<=n<=1000000),m(0<=m<=17)分别表示节点个数以及限制个数。
第2行到第m+1行描述m个限制条件,第i+1行为2个整数u[i],d[i],表示编号为u[i]的节点度数不能为d[i]。
为了方便起见,保证1<=ui<=m。同时保证1<=ui<=n,1<=di<=n-1,保证不会有两条完全相同的限制。
Output
输出一行一个整数表示答案。
Input示例
3 1
1 2
Output示例
2
这题首先要知道prufer编码,对于一个n个点的图,它的生成树的个数是
对于这题,就是告诉你这会你容斥的x个点的度数和是sum,然后公式就是
注意这题还有个坑点就是可能给你的条件里有个同一个点不能有两个度数的要求,所以容斥的时候一定不能出现重复的同一个点
代码:
#include <map>#include <set>#include <stack>#include <queue>#include <cmath>#include <string>#include <vector>#include <cstdio>#include <cctype>#include <cstring>#include <sstream>#include <cstdlib>#include <iostream>#include <algorithm>#pragma comment(linker,"/STACK:102400000,102400000")using namespace std;#define MAX 1000005#define MAXN 1000005#define maxnode 205#define sigma_size 26#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define lrt rt<<1#define rrt rt<<1|1#define middle int m=(r+l)>>1#define LL long long#define ull unsigned long long#define mem(x,v) memset(x,v,sizeof(x))#define lowbit(x) (x&-x)#define pii pair<int,int>#define bits(a) __builtin_popcount(a)#define mk make_pair#define limit 10000//const int prime = 999983;const int INF = 0x3f3f3f3f;const LL INFF = 0x3f3f;const double pi = acos(-1.0);const double inf = 1e18;const double eps = 1e-4;const LL mod = 1e9+7;const ull mx = 133333331;/*****************************************************/inline void RI(int &x) { char c; while((c=getchar())<'0' || c>'9'); x=c-'0'; while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; }/*****************************************************/LL fact[MAX];pii x[20];void init(){ fact[0]=1; for(int i=1;i<=1000000;i++) fact[i]=fact[i-1]*i%mod;}LL qpow(LL a,LL n){ LL ans=1; while(n){ if(n&1) ans=ans*a%mod; a=a*a%mod; n>>=1; } return ans;}int main(){ //freopen("in.txt","r",stdin); init(); int n,m; cin>>n>>m; for(int i=0;i<m;i++){ int a,b; scanf("%d%d",&a,&b); x[i]=mk(a,b); } sort(x,x+m); if(n==1){ printf("1\n"); return 0; } LL ans=qpow(n,n-2); for(int i=1;i<(1<<m);i++){ int flag=0; int k=0; int cnt=0; for(int j=0;j<m;j++){ if((i>>j)&1){ if(k!=x[j].first) k=x[j].first; else{ flag=1; break; } cnt+=x[j].second-1; if(n-2-cnt<0){ flag=1; break; } } } if(flag) continue; LL tmp=fact[n-2]; int num=0; for(int j=0;j<m;j++){ if((i>>j)&1){ num++; tmp=tmp*qpow(fact[x[j].second-1],mod-2)%mod; } } LL ret=(qpow(n-num,n-2-cnt)*tmp%mod)*qpow(fact[n-2-cnt],mod-2)%mod; if(num%2) ans-=ret; else ans+=ret; } cout<<(ans%mod+mod)%mod<<endl; return 0;}
- 51nod 1806 wangyurzee的树(prufer编码求生成树的个数)
- 51nod 1806 wangyurzee的树
- 51Nod-1806-wangyurzee的树
- 51nod 1806 wangyurzee的树
- 51nod 1806 wangyurzee的树(purfer,容斥原理)
- 51nod 1806 wangyurzee的树[purfer][容斥]
- 51NOD 1806 wangyurzee的树(容斥原理 + 组合数学)
- [容斥+Purfer编码] 51Nod1806 wangyurzee的树
- 【51Nod 1806】wangyurzee
- 树的Prufer 编码和最小生成树计数
- 树的Prufer 编码和最小生成树计数
- Prufer数列编码生成树
- [HNOI2004]树的计数(prufer编码)
- [HNOI2008]明明的烦恼 树的 prufer 编码
- 【bzoj1005】 明明的烦恼——树的prufer编码
- 1211: [HNOI2004]树的计数 (prufer编码,排列组合,质因数分解)
- [HNOI2004]树的计数(prufer编码+组合数学)
- BZOJ 1430: 小猴打架 树的prufer编码
- 符号化crash文件
- Struts1、struts2、webwork三者之间的关系
- linux 下添加用户并赋予root权限
- Java中的static关键字解析
- 修复Xcode7.3插件失效的命令行方法
- 51nod 1806 wangyurzee的树(prufer编码求生成树的个数)
- Fragment切换。radiobutton加fragment切换(附件源码下载)
- RecycleView 的简单使用
- 介绍Fragment、ListView、ViewPager三者用法
- 【转】C++ 字符串与16进制字符串之间的转换
- AngularJS中ui-router全攻略
- 为什么要使用struts2框架
- ReentrantLock
- Java构造和解析Json数据的两种方法(json-lib构造和解析Json数据, org.json构造和解析Json数据)