scc
找只有一个节点的强连通分量,标记。
第一行输出强连通分量个数(不为1个节点)
缩点
建图
找出度为0的点。
超过一个或者该点被标记,puts(“-1”);
else 输出答案。
#include<iostream> #include<cstdio> #include<vector> #include<stack> using namespace std; inline int read(){ int t=1,num=0;char c=getchar(); while(c>‘9‘||c<‘0‘){if(c==‘-‘)t=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){num=num*10+c-‘0‘;c=getchar();} return num*t; } const int N=10010; inline int min(int a,int b){return a<b?a:b;} vector<int> g[N];stack<int> s; int n,m,pre[N],low[N],biao[N],cnt=0,t=0,d[N],ans=0,no[N]; void dfs(int x){ pre[x]=low[x]=++t;s.push(x); for(int i=0;i<g[x].size();i++){ int y=g[x][i]; if(!pre[y]){dfs(y);low[x]=min(low[x],low[y]);} else if(!biao[y])low[x]=min(low[x],pre[y]); } if(pre[x]==low[x]){ int st=-1,tmp=0;cnt++; while(st!=x){ st=s.top();s.pop(); biao[st]=cnt;tmp++; } if(tmp==1)ans--,no[cnt]=1; } } int main() { n=read();m=read(); for(int i=1;i<=m;i++){ int x=read(),y=read(); g[x].push_back(y); } for(int i=1;i<=n;i++) if(!pre[i])dfs(i); printf("%d\n",cnt+ans); for(int i=1;i<=n;i++) for(int j=0;j<g[i].size();j++) if(biao[i]!=biao[g[i][j]]) d[biao[i]]++; int tmp=0; for(int i=1;i<=cnt;i++) if(d[i]==0)tmp=(tmp==0?i:-1); if(tmp==-1||no[tmp]){puts("-1");return 0;} for(int i=1;i<=n;i++) if(biao[i]==tmp)printf("%d ",i); return 0; }
本文由Yzyet编写,网址为www.cnblogs.com/Yzyet。非Yzyet同意,禁止转载,侵权者必究。
时间: 2024-10-25 17:37:30