【缩点】Going from u to v or from v to u?

传送舱:POJ2762

题意:求一张有向图是否弱连通


思路:塔尖缩点以后,若图中为0的度超过2个,则整张图不是弱连通 因为至少2个点不能被到达(或到达别的点),那么这2个点不是弱连通

注意:连通图做多了,没有考虑到非连通图(洋文题坑爹)


具体看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define N 30000
int t,n,m,scc,tot,top,clock,x[N],y[N],dfn[N],low[N],f[N][2],stack[N],head[N],belong[N];
bool instack[N];
struct edge{int v,nxt;}e[N];
void add(int x,int y){e[++tot].v=y; e[tot].nxt=head[x]; head[x]=tot;}
void init(){
tot=clock=top=scc=0;
memset(head,0,sizeof head); memset(e,0,sizeof e);
memset(stack,0,sizeof stack); memset(instack,0,sizeof instack);
memset(dfn,0,sizeof dfn); memset(low,0,sizeof low);
memset(belong,0,sizeof belong); memset(f,0,sizeof f);
}
void tarjan(int u){
dfn[u]=low[u]=++clock; stack[top++]=u; instack[u]=1;
for (int i=head[u];i;i=e[i].nxt){
int v=e[i].v;
if (!dfn[v]){tarjan(v); low[u]=min(low[u],low[v]);}
else if (instack[v]) low[u]=min(low[u],dfn[v]);
}
if (dfn[u]==low[u]){
scc++; int v;
do{v=stack[--top]; instack[v]=0; belong[v]=scc;}while (v!=u);
}
}
int main(){
scanf("%d",&t);
while (t--){
scanf("%d%d",&n,&m);
init();
for (int i=1;i<=m;i++){scanf("%d%d",&x[i],&y[i]); add(x[i],y[i]);}
for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
for (int i=1;i<=m;i++)
if (belong[x[i]]!=belong[y[i]]){f[belong[x[i]]][0]++; f[belong[y[i]]][1]++;}
int tmp=0;
for (int i=1;i<=scc;i++){if (f[i][0]==0) tmp++; if (f[i][1]==0) tmp++;}
if (tmp<=2) puts("Yes"); else puts("No");
}
return 0;
}