tarjan eDCC
Tarian 一遍,标记割边。记录 eDCC(边双联通分量)将 eDCC 缩点。 得到一棵树,树边就是原图的割边。
观察发现.最少需要加(sum+1)/2条边.可以使整个图变为边的双连通图。sum 为缩点后叶节点的个数。
板子
int dfn[N], low[N], tim, dcc[N], cnt, bri[M], du[N];
stack<int> s;
void tarjan(int x, int fa)
{
dfn[x] = low[x] = ++tim;
s.push(x);
for (int i = head[x]; i; i = nxt[i])
{
int y = to[i];
if (!dfn[y])
{ // 若y尚未访问
tarjan(y, i);
low[x] = min(low[x], low[y]);
if (dfn[x] < low[y])
bri[i] = bri[i ^ 1] = 1; // 桥
}
else if (i != (fa ^ 1)) // 不是反边
low[x] = min(low[x], dfn[y]);
}
if (dfn[x] == low[x])
{
++cnt;
while (1)
{
int y = s.top();
s.pop();
dcc[y] = cnt; // eDCC
if (y == x)
break;
}
}
}
int main()
{
cin >> n >> m;
while (m--)
{
cin >> x >> y;
add(x, y), add(y, x);
}
tarjan(1, 0);
for (int i = 2; i <= tot; i++)
if (bri[i])
du[dcc[to[i]]]++; // 度数
for (int i = 1; i <= cnt; i++)
if (du[i] == 1)
sum++; // 叶节点数
printf("%d\n", (sum + 1) / 2);
return 0;
}
本文来自博客园,作者:流氓兔LMT,转载请注明原文链接:https://www.cnblogs.com/-include-lmt/p/18739447

浙公网安备 33010602011771号