Hrbust 1259 HaHa's Morning【状压dp---求拓扑排序方案数】

HaHa's Morning
Time Limit: 1000 MS Memory Limit: 65536 K
Total Submit: 26(14 users) Total Accepted: 9(9 users) Rating:  Special Judge: No
Description
HaHa is so happy today, he is going to participate the 7th Hunan University Programming Contest. He woke up in the morning, and wanted to reach Hunan University as soon as possible, but he realized that he still has N things to do before going on his journey.
At first, HaHa thought there must have N! (The factorial of N) ways to get everything done, however, he soon found that this was impossible at all, for the work has some annoying restrictions: some things must be done before getting some other things done. Now HaHa is interested in the number of ways to get everything done, and he asks you for help, so your task is to find how many ways are there to finish his work.
Input
There are several test cases, each case contains several lines, and the first line of each case is two natural numbers N (that described above) and M ≤ 400 (for the total restrictions for the work).
The next M lines describes the restrictions, for each line, there is two positive integers A, B, for the A-th thing must be done before the B-th thing.
The input will finish with the end of file, input is guaranteed that 1 ≤ A, B ≤ N ≤ 17.
Output
For each the case, output one number: the ways to finish the work.
Sample Input
3 2
1 3
2 3
2 2
1 2
2 1
Sample Output

2

0

 

Hint
Way 1: The order to do things is 1, 2, 3.
Way 2: The order to do things is 2, 1, 3.
Source
Hunan University 2011 the 7th Programming Contest
Recommend
万祥

题目大意:


一个N个点的有向图,有M条有向边,问你拓扑排序可行的方式有多少种。


思路:


看到数据量,很显然的状压dp。


如果我们直接正向Dp直接跑拓扑排序去dp的话,假设存在这样一种情况:
1-->4

2-->3

3-->4

那么可行序列有:

1234,2134,2314.

对于我们当前拓扑排序过程中,我们可能先遍历的点是1,也有可能先是2.所以可能会导致结果为2.使得结果错误。


所以我们考虑反向Dp................

对于一个点i来讲,如果其所有儿子节点都排列成功了,那么这个点也就排列成功了。

那么设定dp【i】表示排列成功的状态为i所可行的方案数个数。

那么就有Dp【q】+=dp【v】,q=v+(1<

其中需要满足v&son[i]==son[i]&&v&(1<


Ac代码:

#include
#include
using namespace std;
#define ll long long int
int n,m;
ll dp[(1<<19)];
int son[19];
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(son,0,sizeof(son));
        memset(dp,0,sizeof(dp));
        for(int i=0;i0)
            {
                for(int j=0;j






你可能感兴趣的:(dp)