swjtu 1028: HaHa's Morning

1028: HaHa's Morning

Time Limit: 1 Sec  Memory Limit: 32 MB Submit: Solved: 2 [Submit][Status][Web Board]

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.

 
 
拓扑排序  输出有多少种排序方案。
 
但是。。超时了。
待改进
 1 #include  <iostream>
 2 #include  <algorithm>
 3 #include <vector>
 4 #include <queue>
 5 #include <stdio.h>
 6 #include <string.h>
 7 using namespace std;
 8 
 9 int n;
10 int degree[10005],visit[4005];
11 int x;
12 int best;
13 vector <int> pre[10005];
14 
15 void Topsort(int i)
16 {
17     int j;
18     if(i==n)
19     {
20         best++;
21         return;
22     }
23     for(i=1;i<=n;i++)
24         if(degree[i]==0 && visit[i]==0)
25         {
26             for(j=0;j<pre[i].size();j++)
27             {
28                 x=pre[i][0];
29                 degree[x]--;
30             }
31             visit[i]=1;
32             Topsort(i+1);
33             visit[i]=0;
34             for(j=0;j<pre[i].size();j++)
35             {
36                 x=pre[i][j];
37                 degree[x]++;
38             }
39         }
40 }
41 
42 int main()
43 {
44     int i,j,k,m,p,q;
45     while(~scanf("%d%d",&n,&m))
46     {
47         memset(degree,0,sizeof(degree));
48         memset(pre,0,sizeof(pre));
49         memset(visit,0,sizeof(visit));
50         while(m--)
51         {
52             cin>>p>>q;
53             pre[p].push_back(q);
54             degree[q]++;
55         }
56         best=0;
57         Topsort(1);
58         cout<<best<<endl;
59     }
60 
61     return 0;
62 }
View Code

下面贴上一种状态压缩DP代码,完全是复制黏贴。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #define clr(x)memset(x,0,sizeof(x))
 4 int g[18][18];
 5 long long dp[1<<18];
 6 int n;
 7 long long c_c(int s)
 8 {
 9     long long res=dp[s];
10     if(res>=0)
11         return res;
12     int i,j;
13     for(i=0;i<n;i++)        // 判断是否有冲突的情况
14         if(s&(1<<i))
15             for(j=0;j<n;j++)
16                 if(g[j][i]&&!(s&(1<<j)))
17                     return dp[s]=0;
18     dp[s]=0;
19     for(j=s;j;j^=i)
20     {
21         i=j&-j;
22         dp[s]+=c_c(s^i);
23     }
24     return dp[s];
25 }
26 int main()
27 {
28     int flag,m,a,b,i,j,k,st,stat;
29     while(scanf("%d%d",&n,&m)!=EOF)
30     {
31         flag=0;
32         clr(g);
33         while(m--)
34         {
35             scanf("%d%d",&a,&b);
36             g[a-1][b-1]=1;
37         }
38         for(k=0;k<n;k++)
39             for(i=0;i<n;i++)
40                 if(g[i][k])
41                 for(j=0;j<n;j++)
42                     g[i][j]=g[i][j]||(g[i][k]&&g[k][j]);
43         // 是否有环
44         for(i=0;i<n;i++)
45             if(g[i][i])
46                 break;
47         if(i<n)
48         {
49             printf("0\n");
50             continue;
51         }
52         st=(1<<n)-1;  // 总状态数
53         memset(dp,0xff,sizeof(dp));
54         dp[0]=1;
55         printf("%lld\n",c_c(st));
56     }
57     return 0;
58 }
View Code

 

 

posted @ 2013-05-29 22:03  蛋丁  阅读(269)  评论(1编辑  收藏  举报