题目链接:http://poj.org/problem?id=2762
思路:首先当然是要缩点建新图,由于题目要求是从u->v或从v->u连通,显然是要求单连通了,也就是要求一条长链了,最后只需判断链长是否等于新图顶点个数即可,至于如何求一条链长,直接dfs即可,注意点就是dfs是要从入度为0的顶点开始。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stack> 6 #include<vector> 7 using namespace std; 8 #define MAXN 1010 9 10 int low[MAXN],dfn[MAXN],color[MAXN]; 11 bool mark[MAXN]; 12 int to[MAXN]; 13 int n,m,cnt,_count,ans; 14 15 vector<vector<int> >map; 16 vector<vector<int> >Graph; 17 stack<int>S; 18 19 void Tarjan(int u) 20 { 21 low[u]=dfn[u]=++cnt; 22 mark[u]=true; 23 S.push(u); 24 for(int i=0;i<map[u].size();i++){ 25 int v=map[u][i]; 26 if(dfn[v]==0){ 27 Tarjan(v); 28 low[u]=min(low[u],low[v]); 29 }else if(mark[v]){ 30 low[u]=min(low[u],dfn[v]); 31 } 32 } 33 if(low[u]==dfn[u]){ 34 int v; 35 _count++; 36 do{ 37 v=S.top(); 38 S.pop(); 39 mark[v]=false; 40 color[v]=_count; 41 }while(u!=v); 42 } 43 } 44 45 void dfs(int u) 46 { 47 mark[u]=true; 48 for(int i=0;i<Graph[u].size();i++){ 49 int v=Graph[u][i]; 50 if(!mark[v]){ 51 ans++; 52 dfs(v); 53 return ; 54 } 55 } 56 } 57 58 int main() 59 { 60 int u,v,_case; 61 scanf("%d",&_case); 62 while(_case--){ 63 scanf("%d%d",&n,&m); 64 map.clear();Graph.clear(); 65 map.resize(n+2);Graph.resize(n+2); 66 cnt=_count=0; 67 for(int i=1;i<=m;i++){ 68 scanf("%d%d",&u,&v); 69 map[u].push_back(v); 70 } 71 memset(dfn,0,(n+2)*sizeof(int)); 72 memset(to,0,(n+2)*sizeof(int)); 73 memset(mark,false,(n+2)*sizeof(bool)); 74 for(int i=1;i<=n;i++){ 75 if(dfn[i]==0)Tarjan(i); 76 } 77 for(int i=1;i<=n;i++){ 78 for(int j=0;j<map[i].size();j++){ 79 if(color[i]!=color[map[i][j]]){ 80 Graph[color[i]].push_back(color[map[i][j]]); 81 to[color[map[i][j]]]++; 82 } 83 } 84 } 85 ans=1; 86 for(int i=1;i<=_count;i++){ 87 if(to[i]==0){ dfs(i);break; } 88 } 89 (ans==_count)?puts("Yes"):puts("No"); 90 } 91 return 0; 92 }