题目大意:
判断一个有向图是否弱连通。
思路:
Tarjan缩点。然后判断原图是否是一条链。
考虑链的特性:有且仅有一点入度为0,有且仅有一点出度为0。
因此缩点后直接判断入度为0和出度为0的点的个数是否均为1即可。
1 #include<stack> 2 #include<cstdio> 3 #include<cctype> 4 #include<vector> 5 #include<cstring> 6 inline int getint() { 7 char ch; 8 while(!isdigit(ch=getchar())); 9 int x=ch^‘0‘; 10 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^‘0‘); 11 return x; 12 } 13 const int V=1001; 14 std::vector<int> e[V]; 15 inline void add_edge(const int u,const int v) { 16 e[u].push_back(v); 17 } 18 int dfn[V],low[V],scc[V],in[V],out[V],cnt,id; 19 bool ins[V]; 20 std::stack<int> s; 21 inline void init() { 22 for(int i=0;i<V;i++) e[i].clear(); 23 memset(dfn,0,sizeof dfn); 24 memset(low,0,sizeof low); 25 memset(scc,0,sizeof scc); 26 memset(ins,0,sizeof ins); 27 memset(in,0,sizeof in); 28 memset(out,0,sizeof out); 29 cnt=id=0; 30 } 31 void Tarjan(const int x) { 32 dfn[x]=low[x]=++cnt; 33 s.push(x); 34 ins[x]=true; 35 for(unsigned i=0;i<e[x].size();i++) { 36 int &y=e[x][i]; 37 if(!dfn[y]) { 38 Tarjan(y); 39 low[x]=std::min(low[x],low[y]); 40 } 41 else if(ins[y]) { 42 low[x]=std::min(low[x],dfn[y]); 43 } 44 } 45 if(dfn[x]==low[x]) { 46 int y; 47 ++id; 48 do { 49 y=s.top(); 50 s.pop(); 51 ins[y]=false; 52 scc[y]=id; 53 } while(y!=x); 54 } 55 } 56 int main() { 57 for(int T=getint();T;T--) { 58 int n=getint(); 59 init(); 60 for(int m=getint();m;m--) { 61 int u=getint(),v=getint(); 62 add_edge(u,v); 63 } 64 for(int i=1;i<=n;i++) { 65 if(!dfn[i]) Tarjan(i); 66 } 67 for(int x=1;x<=n;x++) { 68 for(unsigned i=0;i<e[x].size();i++) { 69 int &y=e[x][i]; 70 if(scc[x]!=scc[y]) out[scc[x]]++,in[scc[y]]++; 71 } 72 } 73 int cin=0,cout=0; 74 for(int i=1;i<=id;i++) { 75 if(!in[i]) cin++; 76 if(!out[i]) cout++; 77 } 78 puts(cin==1&&cout==1?"Yes":"No"); 79 } 80 return 0; 81 }
时间: 2024-12-15 01:53:33