Network of Schools POJ - 1236

it2022-05-05  96

 

#include <string.h> #include<iostream> #include <stdio.h> const int V = 105; const int E = 1005; const int inf = 0x3f3f3f3f; using namespace std; struct edge { int to, next; } Edge[E]; int head[V], e, n, m; 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是否在栈中 bool cut[V]; int addedge(int u, int v) { Edge[e].to = v; Edge[e].next = head[u]; head[u] = e++; return 0; } //int cont = 0; void tarjan(int u) { int v; dfn[u] = low[u] = ++cnt; 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为所联系的最小值 } 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 CountDegree() { 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; while (~scanf("%d", &n)) { memset(cut, false, sizeof(cut)); e = 0; memset(head, -1, sizeof(head)); for(int i=1; i<=n; i++) { while(scanf("%d",&v) && v!=0) { addedge(i, v); } } int cutn = 0; int in = 0, out = 0; solve(); if (scc == 1) printf("1\n0\n"); else{ CountDegree(); in = 0, out = 0; for (int i=1; i<=scc; ++i){ if (indeg[i] == 0) in++; if (outdeg[i] == 0) out++; } } if(scc != 1) printf("%d\n%d\n", in, (in > out ? in : out)); } return 0; }

 


最新回复(0)