标签:
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 27531 | Accepted: 11077 |
Description
Input
Output
Sample Input
3 3 1 2 2 1 2 3
Sample Output
1
Hint
Source
#include <string.h> #include <stdio.h> #define V 10500 #define E 50500 struct edge { int to, next; }Edge[E]; int head[V], e, n; int indeg[V], outdeg[V]; //点的入度和出度数 int belong[V], low[V], dfn[V], scc, cnt;//dfn[]:遍历到u点的时间; low[]:u点可到达的各点中最小的dfn[v] int S[V], top; bool vis[V];//v是否在栈中 int addedge(int u, int v) { Edge[e].to = v; Edge[e].next = head[u]; head[u] = e++; return 0; } void tarjan(int u) { int v; dfn[u] = low[u] = ++cnt;//开始时dfn[u] == low[u] S[top++] = u;//不管三七二十一进栈 vis[u] = true; for (int i=head[u]; i!=-1; i=Edge[i].next) { v = Edge[i].to; if (dfn[v] == 0)//如果v点还未遍历 { tarjan(v);//向下遍历 low[u] = low[u] < low[v] ? low[u] : low[v];//确保low[u]最小 } else if (vis[v] && low[u] > dfn[v])//v在栈中,修改low[u] low[u] = dfn[v]; } if (dfn[u] == low[u])//u为该强连通分量中遍历所成树的根 { ++scc; do { v = S[--top];//栈中所有到u的点都属于该强连通分量,退栈 vis[v] = false; belong[v] = scc; } while (u != v); } } int solve(){ scc = top = cnt = 0; memset(dfn, 0, sizeof(dfn)); memset(vis, false, sizeof(vis)); for (int u=1; u<=n; ++u) if (dfn[u] == 0) tarjan(u); return scc; } void count_deg() { memset(indeg, 0, sizeof(indeg)); memset(outdeg, 0, sizeof(outdeg)); for (int u=1; u<=n; ++u) for (int i=head[u]; i!=-1; i=Edge[i].next) { int v = Edge[i].to; if (belong[u] != belong[v]) { indeg[belong[v]]++; outdeg[belong[u]]++; } } } int main() { int u, v, i; int m; while (~scanf("%d%d", &n,&m)) { e = 0; memset(head, -1, sizeof(head)); for (int i=1;i<=m;i++){ scanf("%d%d",&u,&v); addedge(u, v); } solve(); count_deg(); int num=0,tmp; for(int i = 1; i <= scc; i++) { if(!outdeg[i]) { num++; tmp = i; } } int ans=0; if(num == 1) { for(int i = 1; i <= n; i++) { if(belong[i] == tmp) ans++; } printf("%d\n", ans); } else { printf("0\n"); } } return 0; }
标签:
原文地址:http://www.cnblogs.com/13224ACMer/p/4781453.html