#10098. 「一本通 3.6 例 1」分離的路徑
阿新 • • 發佈:2021-02-04
技術標籤:強連通
如果葉子數(縮點後度為1的點)為1,則至少需要新增0條邊;
否則為(葉子數+1)/ 2;
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stack>
#define mem(a,b) memset(a,b,sizeof(a))
const int N = 202000;
typedef long long ll;
using namespace std;
struct node
{
int u, v, net;
} e[N];
int head[ N], tot, pre[N];
void add(int u, int v)
{
e[++tot].v = v;
e[tot].u = u;
e[tot].net = head[u];
head[u] = tot;
}
int dfn[N], low[N], cnt, s[N], tp;
int scc[N], sc;
int sz[N], n, m, out[N];
void tarjan(int u, int f)
{
low[u] = dfn[u] = ++cnt;
pre[u] = f;
s[++tp] = u;
for (int i = head[u]; i; i = e[i].net)
{
int v = e[i].v;
if (v == f)
continue;
if (!dfn[v])
{
tarjan(v, u);
low[u] = min(low[u], low[v]);
}
else
low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[ u])
{
++sc;
while (s[tp] != u)
{
scc[s[tp]] = sc;
--tp;
}
scc[s[tp]] = sc, --tp;
}
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
add(u, v);
add(v, u);
}
// printf("---\n");
for (int i = 1; i <= n; i++)
{
if (!dfn[i])
tarjan(i, i);
}
for (int u = 1; u <= n; u++)
{
if (scc[u] != scc[pre[u]])
{
sz[scc[u]]++;
sz[scc[pre[u]]]++;
}
}
int ans = 0;
for (int i = 1; i <= sc; i++)
{
if (sz[i] == 1)
ans++;
}
printf("%d\n", (ans + 1) >> 1);
return 0;
}