给你一个有向图,然后问你,加入多少条边,能使这个图构成成一个强连通分量
首先,把强连通分量缩成一个点,然后现在就成了一个dag,这个dag中 看只有入度 和只有出度的点 取max就好了
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <stack> #include <vector> #include <map> #include <algorithm> using namespace std; const int MaxN = 50000, MaxM = 200000; int T, n, m, all, Timetot, Scctot; int pre[MaxM + 5], last[MaxN + 5], other[MaxM + 5]; int pr[MaxM + 5], las[MaxN + 5], oth[MaxM + 5]; int dfn[MaxN + 5], low[MaxN + 5], col[MaxN + 5]; int ind[MaxN + 5], oud[MaxN + 5]; bool usedind[MaxN + 5], usedoud[MaxN + 5], usedused[MaxN + 5]; stack <int> sta; vector <int> Scc[MaxN + 5]; map <pair<int, int>, bool> used; void Build(int x, int y) { pre[++all] = last[x]; last[x] = all; other[all] = y; } void Init() { all = -1; memset(last, -1, sizeof(last)); scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { int u, v; scanf("%d%d", &u, &v); Build(u, v); } } void Dfs_Scc(int x, int fa) { dfn[x] = low[x] = ++Timetot; sta.push(x); //强连通分量 存点不存边 int ed = last[x], dr; while (ed != -1) { dr = other[ed]; if (!dfn[dr]) { Dfs_Scc(dr, x); low[x] = min(low[x], low[dr]); } else if (!col[dr] && dfn[dr] < dfn[x]) { low[x] = min(low[x], dfn[dr]); } ed = pre[ed]; } if (low[x] >= dfn[x]) { //强连通分量注意是while出来以后判 Scc[++Scctot].clear(); while (true) { int u = sta.top(); sta.pop(); col[u] = Scctot; Scc[Scctot].push_back(u); if (u == x) break; } } } void rBuild(int x, int y) { pr[++all] = las[x]; las[x] = all; oth[all] = y; ind[x]++; oud[y]++; } void ReBuildGraph() { used.clear(); all = -1; memset(las, -1, sizeof(las)); //all用原来的,las也记得清成-1 for (int i = 1; i <= n; i++) { int ed = last[i], dr; while (ed != -1) { dr = other[ed]; if (col[i] != col[dr] && !used[make_pair(col[i], col[dr])]) { used[make_pair(col[i], col[dr])] = true; rBuild(col[i], col[dr]); } ed = pre[ed]; } } } void Solve() { Timetot = Scctot = 0; memset(dfn, 0, sizeof(dfn)); //dfn, low每次必须清空 memset(low, 0, sizeof(low)); memset(col, 0, sizeof(col)); memset(ind, 0, sizeof(ind)); memset(oud, 0, sizeof(oud)); for (int i = 1; i <= n; i++) if (!dfn[i]) Dfs_Scc(i, -1); ReBuildGraph(); memset(usedused, 0, sizeof(usedused)); int num = 0; for (int i = 1; i <= n; i++) { if (!usedused[col[i]]) { usedused[col[i]] = true; num++; } } memset(usedind, 0, sizeof(usedind)); memset(usedoud, 0, sizeof(usedoud)); int sum_ind = 0, sum_oud = 0; for (int i = 1; i <= n; i++) { if (ind[col[i]] == 0 && !usedind[col[i]]) { usedind[col[i]] = true; sum_ind++; } if (oud[col[i]] == 0 && !usedoud[col[i]]) { usedoud[col[i]] = true; sum_oud++; } } if (num == 1) printf("0\n"); else printf("%d\n", max(sum_ind, sum_oud)); } int main() { scanf("%d", &T); for (int cas = 1; cas <= T; cas++) { Init(); Solve(); } return 0; }
#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <stack>#include <vector>#include <map>#include <algorithm>usingnamespacestd; constint MaxN = 50000, MaxM = 200000; int T, n, m, all, Timetot, Scctot; int pre[MaxM + 5], last[MaxN + 5], other[MaxM + 5]; int pr[MaxM + 5], las[MaxN + 5], oth[MaxM + 5]; int dfn[MaxN + 5], low[MaxN + 5], col[MaxN + 5]; int ind[MaxN + 5], oud[MaxN + 5]; bool usedind[MaxN + 5], usedoud[MaxN + 5], usedused[MaxN + 5]; stack <int> sta; vector <int> Scc[MaxN + 5]; map <pair<int, int>, bool> used; void Build(int x, int y) { pre[++all] = last[x]; last[x] = all; other[all] = y; } void Init() { all = -1; memset(last, -1, sizeof(last)); scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { int u, v; scanf("%d%d", &u, &v); Build(u, v); } } void Dfs_Scc(int x, int fa) { dfn[x] = low[x] = ++Timetot; sta.push(x); //强连通分量 存点不存边int ed = last[x], dr; while (ed != -1) { dr = other[ed]; if (!dfn[dr]) { Dfs_Scc(dr, x); low[x] = min(low[x], low[dr]); } elseif (!col[dr] && dfn[dr] < dfn[x]) { low[x] = min(low[x], dfn[dr]); } ed = pre[ed]; } if (low[x] >= dfn[x]) { //强连通分量注意是while出来以后判 Scc[++Scctot].clear(); while (true) { int u = sta.top(); sta.pop(); col[u] = Scctot; Scc[Scctot].push_back(u); if (u == x) break; } } } void rBuild(int x, int y) { pr[++all] = las[x]; las[x] = all; oth[all] = y; ind[x]++; oud[y]++; } void ReBuildGraph() { used.clear(); all = -1; memset(las, -1, sizeof(las)); //all用原来的,las也记得清成-1for (int i = 1; i <= n; i++) { int ed = last[i], dr; while (ed != -1) { dr = other[ed]; if (col[i] != col[dr] && !used[make_pair(col[i], col[dr])]) { used[make_pair(col[i], col[dr])] = true; rBuild(col[i], col[dr]); } ed = pre[ed]; } } } void Solve() { Timetot = Scctot = 0; memset(dfn, 0, sizeof(dfn)); //dfn, low每次必须清空memset(low, 0, sizeof(low)); memset(col, 0, sizeof(col)); memset(ind, 0, sizeof(ind)); memset(oud, 0, sizeof(oud)); for (int i = 1; i <= n; i++) if (!dfn[i]) Dfs_Scc(i, -1); ReBuildGraph(); memset(usedused, 0, sizeof(usedused)); int num = 0; for (int i = 1; i <= n; i++) { if (!usedused[col[i]]) { usedused[col[i]] = true; num++; } } memset(usedind, 0, sizeof(usedind)); memset(usedoud, 0, sizeof(usedoud)); int sum_ind = 0, sum_oud = 0; for (int i = 1; i <= n; i++) { if (ind[col[i]] == 0 && !usedind[col[i]]) { usedind[col[i]] = true; sum_ind++; } if (oud[col[i]] == 0 && !usedoud[col[i]]) { usedoud[col[i]] = true; sum_oud++; } } if (num == 1) printf("0\n"); elseprintf("%d\n", max(sum_ind, sum_oud)); } int main() { scanf("%d", &T); for (int cas = 1; cas <= T; cas++) { Init(); Solve(); } return0; }