题意是给出一个连通图, 问如果切断任何一条边仍使图是连通的话至少要加几条边.
于是求关键边, 关键边连成一棵树, 易证在叶子处连边是最优的.
在网上看了几篇这题的代码, 都说成求块或者求重连通分量, 其实是错的, 重连通分量只跟关键点有关, 而这题要的是关键边, 只能说是数据太弱了.
#include <iostream>
#include <vector>
#define MAXN 1005
using namespace std;
vector<int> map[MAXN];
int dfn[MAXN], low[MAXN], deep, color[MAXN], com;
void dfs(int i, int f)
{
dfn[i] = low[i] = ++deep;
for (int j = 0; j < map[i].size(); j++)
{
int k = map[i][j];
if (!dfn[k])
{
dfs(k, i);
low[i] = min(low[i], low[k]);
}
else if (k != f)
low[i] = min(low[i], dfn[k]);
}
}
void set_color(int i)
{
for(int j = 0; j < map[i].size(); j++)
{
int k = map[i][j];
if (!color[k])
{
if (low[k] > dfn[i]) color[k] = ++com;
else color[k] = color[i];
set_color(k);
}
}
}
void biconnected(int n)
{
deep = 0;
dfs(0, -1);
com = 1;
color[0] = 1;
set_color(0);
}
int du[MAXN]; //桥的度, 用来判叶子
int main()
{
int n, r, a, b;
scanf("%d %d", &n, &r);
while (r--)
{
scanf("%d %d", &a, &b);
a--; b--;
map[a].push_back(b);
map[b].push_back(a);
}
biconnected(n);
for (int i = 0; i < n; i++)
{
a = color[i];
for (int j = 0; j < map[i].size(); j++)
{
b = color[map[i][j]];
if (a != b) du[a]++;
}
}
int leap = 0;
for (int i = 1; i <= com; i++)
if (du[i] == 1)
leap++;
printf("%d\n", (leap+1)/2);
return 0;
}
#include <vector>
#define MAXN 1005
using namespace std;
vector<int> map[MAXN];
int dfn[MAXN], low[MAXN], deep, color[MAXN], com;
void dfs(int i, int f)
{
dfn[i] = low[i] = ++deep;
for (int j = 0; j < map[i].size(); j++)
{
int k = map[i][j];
if (!dfn[k])
{
dfs(k, i);
low[i] = min(low[i], low[k]);
}
else if (k != f)
low[i] = min(low[i], dfn[k]);
}
}
void set_color(int i)
{
for(int j = 0; j < map[i].size(); j++)
{
int k = map[i][j];
if (!color[k])
{
if (low[k] > dfn[i]) color[k] = ++com;
else color[k] = color[i];
set_color(k);
}
}
}
void biconnected(int n)
{
deep = 0;
dfs(0, -1);
com = 1;
color[0] = 1;
set_color(0);
}
int du[MAXN]; //桥的度, 用来判叶子
int main()
{
int n, r, a, b;
scanf("%d %d", &n, &r);
while (r--)
{
scanf("%d %d", &a, &b);
a--; b--;
map[a].push_back(b);
map[b].push_back(a);
}
biconnected(n);
for (int i = 0; i < n; i++)
{
a = color[i];
for (int j = 0; j < map[i].size(); j++)
{
b = color[map[i][j]];
if (a != b) du[a]++;
}
}
int leap = 0;
for (int i = 1; i <= com; i++)
if (du[i] == 1)
leap++;
printf("%d\n", (leap+1)/2);
return 0;
}