HDU 3836 Equivalent Sets(强连通分量)
Posted AC_Arthur
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3836 Equivalent Sets(强连通分量)相关的知识,希望对你有一定的参考价值。
题目链接:点击打开链接
思路:强连通分量模板题, 把一个强连通分量的缩成一个点, 构建一张新图。 然后在新图上, 求每个点的入度和出度。 假设有a个顶点的入度为0,b个顶点的出度为0,那么可以证明答案就是max(a, b)。 可以这么想, 入度为0的点肯定要练到出度为0的点。
细节参见代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <string> #include <vector> #include <stack> #include <bitset> #include <cstdlib> #include <cmath> #include <set> #include <list> #include <deque> #include <map> #include <queue> #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) using namespace std; typedef long long ll; typedef long double ld; const ld eps = 1e-9, PI = 3.1415926535897932384626433832795; const int mod = 1000000000 + 7; const int INF = 0x3f3f3f3f; // & 0x7FFFFFFF const int seed = 131; const ll INF64 = ll(1e18); const int maxn = 20000 + 10; int T,n,m,u,v,pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt; vector<int> g[maxn]; stack<int> S; void dfs(int u) { pre[u] = lowlink[u] = ++dfs_clock; S.push(u); int len = g[u].size(); for(int i = 0; i < len; i++) { int v = g[u][i]; if(!pre[v]) { dfs(v); lowlink[u] = min(lowlink[u], lowlink[v]); } else if(!sccno[v]) { lowlink[u] = min(lowlink[u], pre[v]); } } if(lowlink[u] == pre[u]) { scc_cnt++; for(;;) { int x = S.top(); S.pop(); sccno[x] = scc_cnt; if(x == u) break; } } } void find_scc(int n) { for(int i = 1; i <= n; i++) { if(!pre[i]) dfs(i); } } int in0[maxn], out0[maxn]; void init(int n) { dfs_clock = scc_cnt = 0; for(int i = 1; i <= n; i++) { g[i].clear(); sccno[i] = pre[i] = 0; } } int main() { while(~scanf("%d%d",&n,&m)) { init(n); for(int i = 1; i <= m; i++) { scanf("%d%d",&u,&v); g[u].push_back(v); } find_scc(n); if(scc_cnt == 1) { printf("0\n"); continue; } for(int i = 1; i <= scc_cnt; i++) in0[i] = out0[i] = 1; for(int u = 1; u <= n; u++) { int len = g[u].size(); for(int j = 0; j < len; j++) { int v = g[u][j]; if(sccno[u] != sccno[v]) in0[sccno[v]] = out0[sccno[u]] = 0; } } int a = 0, b = 0; for(int i = 1; i <= scc_cnt; i++) { if(in0[i]) a++; if(out0[i]) b++; } int ans = max(a, b); printf("%d\n", ans); } return 0; }
以上是关于HDU 3836 Equivalent Sets(强连通分量)的主要内容,如果未能解决你的问题,请参考以下文章
hdu 3836 Equivalent Sets trajan缩点
hdu 3836 Equivalent Sets(强连通分量--加边)
HDU 3836 Equivalent Sets(强连通分量)