poj2762
http://poj.org/problem?id=2762
强连通缩点不解释,one-way corridors connecting some rooms注意路径是单向的。
缩点以后,根据题目描述任取两点都有路径连通,随意画一个DAG会发现总有一条路可以连接所有节点,猜测这个规则是否成立。
有点集S,s,s是S的一个子集,DAG中找到一个出度为0的节点a,入度为0的节点b,将该a,b加入s中,从S中出去a,b,有条件可知a~b有路径连通,然后从S中任意拿出一个节点k,条件可知a~k~b,将k加入s中,从S中出去k,接下来同样取点,取出来的节点由于条件可知一点可以放入某个~中,当S为空时,则形成了一条连接所有节点的路径。
所以运用该规则判断缩点后DAG是否具有这样一条路径即可。
判断有两种方法,一种是dfs求出最大的深度与节点数比较,一种是不断消去入度为0的节点,直到没有节点或出现1个以上的入度为0的节点。
Gabow缩点,判断用后一中方法。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h>
2 #include <memory.h>
3 #define SIZE 1001
4 #define E 6001
5 struct node
6 {
7 int end;
8 node*next;
9 }edge[E],*head[SIZE],*p,Edge[E],*Head[SIZE],*q;
10 int root_stack[SIZE],stack[SIZE],belong[SIZE],init[SIZE],in[SIZE];
11 int n,m,cnt,father;
12 void ini()
13 {
14 memset(head,NULL,sizeof(head));
15 memset(Head,NULL,sizeof(Head));
16 memset(root_stack,0,sizeof(root_stack));
17 memset(stack,0,sizeof(stack));
18 memset(belong,0,sizeof(belong));
19 memset(init,0,sizeof(init));
20 memset(in,0,sizeof(in));
21 }
22 void add(int a,int b)
23 {
24 p->end=b;
25 p->next=head[a];
26 head[a]=p++;
27 }
28 void Add(int a,int b)
29 {
30 q->end=b;
31 q->next=Head[a];
32 Head[a]=q++;
33 }
34 void Gabow(int key)
35 {
36 root_stack[++root_stack[0]]=stack[++stack[0]]=key;
37 init[key]=++cnt;
38 for(node*tmp=head[key];tmp;tmp=tmp->next)
39 {
40 if(!init[tmp->end])
41 Gabow(tmp->end);
42 else if(!belong[tmp->end])
43 while(init[root_stack[root_stack[0]]]>init[tmp->end])
44 --root_stack[0];
45 }
46 if(root_stack[root_stack[0]]==key)
47 {
48 ++father,--root_stack[0];
49 do
50 belong[stack[stack[0]]]=father;
51 while(stack[stack[0]--]!=key);
52 }
53 }
54 int main()
55 {
56 int sum_case;
57 scanf("%d",&sum_case);
58 while(sum_case--)
59 {
60 scanf("%d %d",&n,&m);
61 p=edge;
62 for(int i=0,a,b;i<m;++i)
63 {
64 scanf("%d %d",&a,&b);
65 add(a,b);
66 }
67 cnt=father=0;
68 for(int i=1;i<=n;++i)
69 if(!init[i])
70 Gabow(i);
71 q=Edge;
72 for(int i=1;i<=n;++i)
73 for(node*tmp=head[i];tmp;tmp=tmp->next)
74 if(belong[i]!=belong[tmp->end])
75 {
76 Add(belong[i],belong[tmp->end]);
77 ++in[belong[tmp->end]];
78 }
79 int num,cnt=0;
80 for(int i=1;i<=father;++i)
81 if(!in[i])
82 num=i,++cnt;
83 if(cnt==1)
84 {
85 while(1)
86 {
87 cnt=0;
88 for(node*tmp=Head[num];tmp;tmp=tmp->next)
89 {
90 --in[tmp->end];
91 if(!in[tmp->end])
92 num=tmp->end,++cnt;
93 }
94 if(!cnt)
95 {
96 printf("Yes\n");
97 break;
98 }
99 if(cnt!=1)
100 {
101 printf("No\n");
102 break;
103 }
104 }
105 }
106 else
107 printf("No\n");
108 ini();
109 }
110 return 0;
111 }
tarjan缩点,判断用前一种
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h>
2 #include <memory.h>
3 #define MIN(a,b) ((a)<(b)?(a):(b))
4 #define MAX(a,b) ((a)>(b)?(a):(b))
5 #define SIZE 1001
6 struct node
7 {
8 int end;
9 node*next;
10 }edge[6*SIZE],*head[SIZE],*p,Edge[6*SIZE],*Head[SIZE],*q;
11 int dfn[SIZE],low[SIZE],stack[SIZE],belong[SIZE],in[SIZE],max[SIZE];
12 bool visit[SIZE];
13 int cnt,father,boss;
14 void bulid(int a,int b)
15 {
16 p->end=b;
17 p->next=head[a];
18 head[a]=p++;
19 }
20 void add(int a,int b)
21 {
22 q->end=b;
23 q->next=Head[a];
24 Head[a]=q++;
25 ++in[b];
26 }
27 void tarjan(int key)
28 {
29 dfn[key]=low[key]=++cnt;
30 stack[++stack[0]]=key;
31 visit[key]=true;
32 for(node*tmp=head[key];tmp;tmp=tmp->next)
33 {
34 if(!low[tmp->end])
35 {
36 tarjan(tmp->end);
37 low[key]=MIN(low[key],low[tmp->end]);
38 }
39 else if(visit[tmp->end])
40 low[key]=MIN(low[key],dfn[tmp->end]);
41 }
42 if(dfn[key]==low[key])
43 {
44 ++father;
45 do
46 {
47 belong[stack[stack[0]]]=father;
48 visit[stack[stack[0]]]=false;
49 }
50 while(stack[stack[0]--]!=key);
51 }
52 }
53 void ini()
54 {
55 memset(stack,0,sizeof(stack));
56 memset(dfn,0,sizeof(dfn));
57 memset(low,0,sizeof(low));
58 memset(in,0,sizeof(in));
59 memset(max,0,sizeof(max));
60 memset(visit,false,sizeof(visit));
61 memset(Head,NULL,sizeof(Head));
62 memset(head,NULL,sizeof(head));
63 }
64 void dfs(int key)
65 {
66 for(node*tmp=Head[key];tmp;tmp=tmp->next)
67 {
68 if(!max[tmp->end])
69 dfs(tmp->end);
70 max[key]=MAX(max[key],max[tmp->end]);
71 }
72 ++max[key];
73 boss=MAX(boss,max[key]);
74 }
75 int main()
76 {
77 int num_case;
78 scanf("%d",&num_case);
79 while(num_case--)
80 {
81 int n,m;
82 scanf("%d %d",&n,&m);
83 p=edge;
84 for(int i=0,a,b;i<m;++i)
85 {
86 scanf("%d %d",&a,&b);
87 bulid(a,b);
88 }
89 cnt=father=0;
90 for(int i=1;i<=n;++i)
91 if(!low[i])
92 tarjan(i);
93 q=Edge;
94 for(int i=1;i<=n;++i)
95 for(node*tmp=head[i];tmp;tmp=tmp->next)
96 if(belong[i]!=belong[tmp->end])
97 add(belong[i],belong[tmp->end]);
98 int one;
99 cnt=0;
100 for(int i=1;i<=father;++i)
101 if(!in[i])
102 one=i,++cnt;
103 if(cnt>1)
104 printf("No\n");
105 else
106 {
107 boss=0;
108 dfs(one);
109 if(boss==father)
110 printf("Yes\n");
111 else
112 printf("No\n");
113 }
114 ini();
115 }
116 return 0;
117 }