链接地址:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1058
这道题求的是一个工作图完成所需要的最短时间(任何一个end完成就算结束),刚开始看这道题以为是什么dp,但是把图画出来一看发现根本不是树,求最短时间,最短步数,首先想到广搜,注意这里给出的条件是,如果这个点的值是true需要把所有的前序工作都做完之后才可以做这件工作,那么我们对于是true的节点在广搜时何时入队就要进行一下判断,那么什么时候他才可以入队呢?很明显,对应图中的一个点有一个入度,当其前继节点都结束之后他才可以入队,那么我们最先搜到的end节点的步数,就是最短时间了而对于是false的节点,能入队直接入队就可以了,代码如下
View Code
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<vector>
5 #include<queue>
6 #define max 1e9
7 using namespace std;
8 bool map[105][105];
9 int degree[105];
10 int num[105];
11 bool heaf[105];
12 bool used[105];
13 bool tof[105];
14 struct point
15 {
16 int no;
17 int step;
18 };
19 int main()
20 {
21 int t;
22 int n,m,i,j,k;
23 int root;
24 int hnum;
25 scanf("%d",&t);
26 int start,end;
27 queue<point> q;
28 while(t--)
29 {
30 bool p=false;
31 while(!q.empty())
32 q.pop();
33 int temp;
34 scanf("%d%d",&n,&m);
35 memset(map,0,sizeof(map));
36 memset(degree,0,sizeof(degree));
37 memset(num,0,sizeof(num));
38 memset(heaf,0,sizeof(heaf));
39 memset(tof,0,sizeof(tof));
40 memset(used,0,sizeof(used));
41 scanf("%d%d",&root,&hnum);
42 for(i=1;i<=hnum;i++)
43 {
44 scanf("%d",&temp);
45 heaf[temp]=true;
46 }
47 for(i=0;i<m;i++)
48 {
49 scanf("%d%d",&start,&end);
50 map[start][end]=true;
51 degree[end]++;
52 }
53 for(i=0;i<n;i++)
54 {
55 scanf("%d",&temp);
56 if(temp)
57 tof[i]=true;
58 }
59 point p1;
60 p1.no=root;
61 p1.step=1;
62 q.push(p1);
63 used[root]=true;
64 while(!q.empty())
65 {
66 point p2=q.front();
67 q.pop();
68 if(heaf[p2.no])
69 {
70 p=true;
71 printf("%d\n",p2.step);
72 break;
73 }
74 for(i=0;i<n;i++)
75 {
76 if(map[p2.no][i]&&!used[i])
77 {
78 if(!tof[i])
79 {
80 used[i]=true;
81 point temp1;
82 temp1.no=i;
83 temp1.step=p2.step+1;
84 q.push(temp1);
85 }
86 else
87 {
88 num[i]++;
89 if(num[i]==degree[i])
90 {
91 used[i]=true;
92 point temp1;
93 temp1.no=i;
94 temp1.step=p2.step+1;
95 q.push(temp1);
96 }
97 }
98 }
99 }
100 }
101 if(!p)
102 printf("-1\n");
103 }
104 return 0;
105 }