题意:求一个有向图中所有满足以下性质的结点:从自身出发可达的点均能回到自身。
分析:求的就是缩点后出度为0的强连通分量内的点。
这题以前写过,当时用邻接表来存储的。今天又试了下矩阵存储,速度慢了一半……
用矩阵存储时,要用char或bool,否则会超内存。
View Code
#include <stdio.h> #include <string.h> #define N 5001 int n,m; char g[N][N],vis[N]; int dfn[N],id[N],cnt; int dout[N]; void dfs(int u) { vis[u]=1; for(int v=1;v<=n;v++) { if(g[u][v] && !vis[v]) dfs(v); } dfn[cnt++]=u; } void rdfs(int u) { vis[u]=1; id[u]=cnt; for(int v=1;v<=n;v++) { if(g[v][u] && !vis[v]) rdfs(v); } } void solve() { int i,j,t; cnt=0; memset(vis+1,0,sizeof(char)*n); for(i=1;i<=n;i++) { if(!vis[i]) dfs(i); } cnt=0; memset(vis+1,0,sizeof(char)*n); for(t=n-1;t>=0;t--) { i=dfn[t]; if(!vis[i]) rdfs(i),cnt++; } memset(dout,0,sizeof(int)*(n+1)); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(g[i][j] && id[i]!=id[j]) dout[id[i]]++; } } for(i=1;i<=n;i++) if(!dout[id[i]]) {printf("%d",i);break;} for(i++;i<=n;i++) if(!dout[id[i]]) printf(" %d",i); puts(""); } int main() { int a,b; while(scanf("%d",&n),n) { for(int i=1;i<=n;i++) memset(g[i],0,sizeof(char)*(n+1)); scanf("%d",&m); while(m--) { scanf("%d%d",&a,&b); g[a][b]=1; } solve(); } return 0; }