首页 > 代码库 > POJ 2186.Popular Cows 解题报告
POJ 2186.Popular Cows 解题报告
强连通缩点,统计入度为1的缩点后的点的个数
个数1的话输出这个强连通分量的点的数量
否则输出0;
code
/* Kosaraju算法,无向图的强连通分量,时间复杂度O(n+m) 思路: 按照图G的深度遍历序列,在G的反图上进行深搜 能够搜到的点集就是一个强联通分量*/#include <iostream>#include <cstring>using namespace std;const int INF = 10009;//链接表,偶数边为原图,奇数边为反图struct node { int v, ne;} edge[100009];/* scc是强连通子图的个数 dfn为深度遍历序列(逆序即反图的拓扑排序) vis为访问标记,sum记录每个强连通分量的节点数*/int head[INF], dfn[INF], vis[INF], sum[INF], n, m, scc, cnt = 1, tol;void adde (int u, int v) { edge[++cnt].v = v; edge[cnt].ne = head[u]; head[u] = cnt;}void dfs (int k) { vis[k] = 1; for (int i = head[k]; i != 0; i = edge[i].ne) if ( (i & 1) == 0 && !vis[edge[i].v]) dfs (edge[i].v); dfn[++tol] = k;}void ndfs (int k) { vis[k] = scc, sum[scc]++; for (int i = head[k]; i != 0; i = edge[i].ne) if ( (i & 1) && !vis[edge[i].v]) ndfs (edge[i].v);}void Kosaraju() { for (int i = 1; i <= n; i++) if (!vis[i]) dfs (i); memset (vis, 0, sizeof vis); for (int i = n; i > 0; i--) if (!vis[dfn[i]]) scc++, ndfs (dfn[i]);}int make() { int deg[INF] = {0}; //由反图统计每个强联通点的有无出度 for (int i = 3; i <= cnt; i += 2) { if (vis[edge[i].v] == vis[edge[i ^ 1].v]) continue; deg[vis[edge[i].v]]++; } int j, t = 0; for (int i = 1; i <= scc; i++) if (deg[i] == 0) j = i, t++; if (t == 1) return sum[j]; return 0;}int main() { int x, y; cin >> n >> m; for (int i = 1; i <= m; i++) { cin >> x >> y; adde (x, y), adde (y, x); } Kosaraju(); cout << make(); return 0;}
POJ 2186.Popular Cows 解题报告
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。