标签:max code img back cstring font continue nbsp print
----我想说说双联通分量还有割点和桥
1.割点(一个点,如果没有这一个点,图就会变得不连通)
2.桥(一条边,断开这条边就会让图不连通)
3.点双连通(没割点的图)
4.边双连通(没桥的图)
5.割点之间不一定有桥!!!
6.桥两端不一定是割点!!!
就像下图,圈住的是点双连通分量和边双连通分量
本题要把有桥图,变成边双连通图,问你要加几条边
下图说了具体做法
这就是我找到的关于双联通分量的见解了
代码奉上
#include<cstdio> #include<cstring> #include<iostream> #include<queue> #include<stack> #include<vector> #include<map> #include<algorithm> #define maxn 5010 #define INF 10000 using namespace std; int low[maxn], dfn[maxn], clor[maxn], df, clr; vector<int>G[maxn]; void insert(int be, int en) { G[be].push_back(en); } int n, m; stack<int>s; int de[maxn]; void tarjan(int x,int fa) { low[x] = dfn[x] = ++df; s.push(x); for (int i = 0; i < G[x].size(); i++) { int p = G[x][i]; if (p == fa) continue; if (!dfn[p]) { tarjan(p, x); low[x] = min(low[x], low[p]); } else { low[x] = min(low[x], dfn[p]); } } if (low[x] == dfn[x]) { clr++; while (1) { int a = s.top(); s.pop(); clor[a] = clr; if (a == x) break; } } } map<long long, int>ins; int main() { int be, en; scanf("%d %d", &n, &m); for (int i = 0; i < m; i++) { scanf("%d %d", &be, &en); long long an = be * INF + en; long long cc = en * INF + be; if (ins[an] == 0 || ins[cc] == 0) { insert(be, en); insert(en, be); ins[cc] = 1; ins[an] = 1; } } for (int i = 1; i <= n; i++) { if (!dfn[i]) tarjan(i, -1); } for (int i = 1; i <= n; i++) { for (int j = 0; j < G[i].size(); j++) { int p = G[i][j]; if (clor[i] != clor[p]) { de[clor[i]]++; de[clor[p]]++; } } } int cnt = 0; for (int i = 1; i <= clr; i++) { if (de[i] == 2) cnt++;//因为一个边有两个端点,每个边都被算计了两次! } printf("%d\n", (cnt + 1) / 2); return 0; }
标签:max code img back cstring font continue nbsp print
原文地址:https://www.cnblogs.com/lesning/p/11627961.html