EOJ:EXPO Journey

EXPO Journey

Time Limit: 1000MS Memory Limit: 65536K

Description

ziRoy would like to visit the EXPO tomorrow and now he wants to make a plan in advance. China pavilion is absolutely a terrific place which ziRoy can’t miss. Thus, he decides to get a reservation ticket of China pavilion at morning and visit it at the end of his EXPO journey.

There are totally N (2 ≤ N ≤ 50) pavilions (numbered 1..N) in the EXPO. Some of them directly connected by paths (you can take each path only in one given direction). And no pair of pavilions is connected by more than one path in the same direction. ziRoy could start at one of the K (1 ≤ K ≤ N – 1) pavilions (none of them is China pavilion) and end at China pavilion. He asks you to help him count the number of routes he can take.

The definition of route is as follows:
  • A legal route is a sequence of pavilions starting with one from given K pavilions and end with China pavilion. Each pavilions on the route other than the last one has a path leading to the next consecutive pavilion.
  • Two routes are distinct if they each have a different sequence of pavilion.
  • A route can have any length.
  • Any pavilion (including China pavilion) may be present multiple times on the route.


If the number of routes is larger than L (1 ≤ L ≤ 108) or infinite, print -1

 

Input

On the first line of the input is a single positive integer T (T ≤ 92), telling the number of test cases to follow. For each test case :
Line 1 : two integer N and M (1 ≤ M ≤ 2500), the number of pavilions and the number of paths.
Line 2..1+M: two integer and indicate the i-th path from Si to Ei .
Line 2+M: an integer K
Line 3+M: K integers indicate the K start pavilions as which ziRoy can choose.
Line 4+M: an integer C indicates China pavilion, which is the end of ziRoy’s EXPO journey.
Line 5+M: an integer L

 

Output

For each test case, output one line with a single integer indicates the number of routes or -1 if the number is larger than L or infinite.

 

Sample Input

2
3 3
1 2
1 3
2 3
2
1 2
3
5
5 5
1 2
2 3
3 4
4 2
4 5
1
1
5
10

 

Sample Output

3
-1
原题地址:http://www.cn210.com/onlinejudge/problemshow.php?pro_id=262
_____________________________________________________________________________________________________
题解:
我是从终点开始反向走回起点,然后将次数累加。当然从起点到终点也可以,不过因为有多个起点,还是从终点做比较方便。
本题最主要的问题就是判断有没有环。
有两种环:
1、环在起点到终点的路程中,这时答案肯定是-1。
2、环不在起点到到终点的路程中,这时环对答案无影响。
判断换的方法很简单,从重点递归的时候标记当前路径走过的点,如果当前走到的点已经被标记过,那么肯定存在环。
麻烦的时候如何判断是哪种环。我的方法是先从每个起点搜一遍,把能从起点到的点标记下。当搜到环的时候判断它能不能到起点,如果不能就是第二种环,能就是第一种环。
代码
1 #include<stdio.h>
2 #include<memory.h>
3  int dp[55],flag[55],circle[55],mark[55],map[55][55];
4  int i,n,m,k,l,a,b,c,t,exceed;
5 void dfs(int u)
6 {
7 int v;
8 circle[u]=1;
9 flag[u]=1;
10 for (v=1;v<=n;v++)
11 if (circle[v]==0&&map[u][v]>0)
12 dfs(v);
13 }
14 void work(int u)
15 {
16 int v;
17 if (mark[u]>0||exceed==1) return;
18 for (v=1;v<=n;v++)
19 if (map[v][u]>0)
20 {
21 circle[v]++;//记录路径,如果当前到达点已经被标记过那么肯定有环
22 if (circle[v]>1)//有环
23 {
24 if (flag[v]==1)
25 {
26 exceed=1;//当前的环能从起点到达,说明环在起点到终点的路径中。
27 return ;
28 }
29 }
30 else work(v);
31 circle[v]--;
32 if (flag[v]==1)
33 {
34 dp[u]+=dp[v];
35 if (dp[u]>l)
36 {
37 exceed=1;
38 return;
39 }
40 }
41 }
42 mark[u]=1;
43 }
44 int main()
45 {
46 scanf("%d",&t);
47 while (t--)
48 {
49 memset(dp,0,sizeof(dp));
50 memset(flag,0,sizeof(flag));
51 memset(mark,0,sizeof(mark));
52 memset(map,0,sizeof(map));
53 scanf("%d%d",&n,&m);
54 for (i=1;i<=m;i++)
55 {
56 scanf("%d%d",&a,&b);
57 map[a][b]=1;
58 }
59 scanf("%d",&k);
60 for (i=1;i<=k;i++)
61 {
62 scanf("%d",&a);
63 memset(circle,0,sizeof(circle));
64 dfs(a);//标记能从起点到达的点
65 dp[a]=1;
66 }
67 scanf("%d%d",&c,&l);
68 memset(circle,0,sizeof(circle));
69 circle[c]=1;
70 exceed=0;
71 work(c);
72 if (exceed==0)
73 printf("%d\n",dp[c]);
74 else printf("-1\n");
75 }
76 return 0;
77 }

 

posted on 2010-08-08 21:14  风也轻云也淡  阅读(103)  评论(0编辑  收藏  举报