边双连通分量还有桥
我发现了两种边双的写法
1.先求桥,标记桥再dfs求连通块,< 似乎有点麻烦
2.直接上有向图的写法,把回头的情况标记一下
其1
int tarjan(int x, int fa) {
low[x] = dfn[x] = ++df;
for (int i = head[x]; i; i = G[i].next) {
int p = G[i].to;
if (!dfn[p]) {
tarjan(p, i);
low[x] = min(low[x], low[p]);
if (low[p] > dfn[x]) {
aaa++;
bri[i] = bri[i ^ 1] = 1;
}
}
else if (fa == -1 || i != (fa ^ 1)) {
low[x] = min(low[x], dfn[p]);
}
}
return 0;
}
int dfss(int x) {
clor[x] = ans;
for (int i = head[x]; i; i = G[i].next) {
int p = G[i].to;
if (clor[p] || bri[i]) continue;
dfss(p);
}
return 0;
}
/////
scanf("%d %lld", &n, &m);
for (int i = 0; i < m; i++) {
scanf("%d%d", &be, &en);
insert(be, en);
insert(en, be);
}
tarjan(1, -1);
for (int i = 1; i <= n; i++) {
if (!clor[i]) {
ans++;
dfss(i);
}
}
ans 就是边双分量
其2.
int low[maxn], dfn[maxn], df, ans;
int clor[maxn];
void insert(int be, int en) {
G[be].push_back(en);
}
int tarjan(int x,int fa) {
low[x] = dfn[x] = ++df;
s.push(x);
int flag=0;
for (int i = 0; i < G[x].size(); i++) {
int p = G[x][i];
if (p == fa){
flag++;
if(flag == 1) continue;//和昆哥学的,标记回头,预防重边
}
if (!dfn[p]) {
tarjan(p, x);
low[x] = min(low[x], low[p]);
}
else if (!clor[p]) {
low[x] = min(dfn[p], low[x]);
}
}
if (dfn[x] == low[x]) {
ans++;
while (1) {
int a = s.top();
clor[a] = ans;
s.pop();
if (a == x) break;
}
}
return 0;
}
////
寻找真正的热爱

浙公网安备 33010602011771号