Permutation
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 316 Accepted Submission(s): 88
Problem Description
bobo has a permutation p
1,p
2,…,p
n of 1,2,…,n.
Knowing m extra constraints of form p ai<p bi, bobo wanna count the number of different permutations modulo (10 9+7).
It is guaranteed that there is at least one such permutation.
Knowing m extra constraints of form p ai<p bi, bobo wanna count the number of different permutations modulo (10 9+7).
It is guaranteed that there is at least one such permutation.
Input
The input consists of several tests. For each tests:
The first line contains n,m (1≤n≤40,0≤m≤20). Each of the following m lines contain 2 integers a i,b i(1≤a i,b i≤n).
The first line contains n,m (1≤n≤40,0≤m≤20). Each of the following m lines contain 2 integers a i,b i(1≤a i,b i≤n).
Output
For each tests:
A single number denotes the number of permutations.
A single number denotes the number of permutations.
Sample Input
3 1 1 2 3 2 1 2 2 3
Sample Output
3 1
题意:求有向无环图的拓扑排序数
思路:状态压缩DP,dp[s]表示集合s中已经拓扑过的点的方案数,则对于点i,如果i不在s中并且i的前驱全部都在s中,则可以转移dp[s|(1<<i)]+=dp[s],为什么是这样转移呢?
因为此时的i节点能够被加进去相当于i的入度已经减为0,则前面的方案数不会影响到新加入的i,直接累加即可。
总的来说为如下公式:
dp[s]=∑dp[s-i] (i为s中入度为0的点)
题目中边的数目不会超过20,所以每个连通块中的点的数量不会超过21,可以用状态压缩
最后的结果等于各个连通块求得的方案数乘以对应的组合数,假如连通块i的节点数为k,剩下还未算的节点数为n(包含这k个节点),则对于当前连通块的组合数为C n k,累
加各个连通块的方案数乘以组合数即是答案
#include
#include
#include
#include
using namespace std;
#define mod (1000000000+7)
typedef __int64 ll;
int ha[45];
int hh[45];
int dp[2097160];
int ss[45];
int n,m;
int d;
int head[45];
int edge[50];
int next[50];
int du[45];
int vis[45];
int cn;
int head1[45];
int edge1[50<<1];
int next1[50<<1];
int d1;
int q[45];
void add(int u,int v)
{
edge[d]=v;
next[d]=head[u];
head[u]=d++;
}
void add1(int u,int v)
{
edge1[d1]=v;
next1[d1]=head1[u];
head1[u]=d1++;
}
void dfs(int u,int s)
{
int i;
for(i=head[u];i!=-1;i=next[i]){
ss[edge[i]]|=s;
dfs(edge[i],ss[edge[i]]|(1<