用tarjan进行缩点,因为所有强连通分量都能互达,因此考虑dag,当且仅当拓扑排序是队列中不超过一个元素存在才是答案。
#include<bits/stdc++.h> using namespace std; const int N=2e5+10; int id[N]; int h[N],ne[N],w[N],e[N],idx; stack<int> q; int scnt; int cnt[N]; int times; int n,m; int dfn[N],low[N]; int ins[N]; int in[N]; vector<int> g[N]; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void tarjan(int u){ int i; dfn[u]=low[u]=times++; q.push(u),ins[u]=1; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(!dfn[j]){ tarjan(j); low[u]=min(low[u],low[j]); } else if(ins[j]) low[u]=min(low[u],dfn[j]); } if(low[u]==dfn[u]){ scnt++; while(1){ int t=q.top();q.pop(); ins[t]=0; id[t]=scnt; if(t==u) break; } } } bool topo(){ int i; queue<int> qi; for(i=1;i<=scnt;i++){ if(!in[i]) qi.push(i); } while(qi.size()){ if(qi.size()>1) return 0; int t=qi.front(); qi.pop(); for(i=0;i<g[t].size();i++){ int k=g[t][i]; in[k]--; if(!in[k]) qi.push(k); } } return true; } int main(){ int t; cin>>t; while(t--){ cin>>n>>m; int i; memset(h,-1,sizeof h); idx=0; scnt=0; times=0; memset(dfn,0,sizeof dfn); memset(low,0,sizeof low); memset(in,0,sizeof in); // memset(id,0,sizeof id); for(i=1;i<=m;i++){ int a,b; scanf("%d%d",&a,&b); add(a,b); } for(i=1;i<=n;i++){ if(!dfn[i]) tarjan(i); } for(i=1;i<=scnt;i++) g[i].clear(); for(i=1;i<=n;i++){ int j; for(j=h[i];j!=-1;j=ne[j]){ int k=e[j]; if(id[i]!=id[k]){ g[id[i]].push_back(id[k]); in[id[k]]++; } } } if(!topo()) cout<<"No"<<endl; else cout<<"Yes"<<endl; } }