公开20190417远古博客,汗
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612
题意:
给n个点m条无向边,保证整体是个连通图,问加一条边之后保留的桥数量最小值
思路:
无向图找桥,tarjan;之后缩点;再之后找到缩点之后由桥当作树边的树的直径,桥数-直径(最长路径长度)即为所求
坑:
1. 没有缩点,直接接拿桥做,这样生成的将会是森林,而且森林中的树也都不是我要的树
2. tot = tc = 0,因为建双向,保证双向可以通过i,i^1完成对一对互为反向边的边的操作,要保证01,23,45。。。
所以可以A. tot = 0,tot ++
B. tot = 1,++ tot
3. 初始化的数组看少了,dfn和c一开始没有初始化,因为看到有赋值以为不用,但是忽略了是有条件的赋值,如果原值 = 0,才会赋值。所以要初始化为零,还有要注意记录数组下标的变量的赋初值,初始化标记数组,还有上述的数组。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
const int maxm = 2e6 + 5;
int head[maxn],ver[maxm],Next[maxm];
int dfn[maxn],low[maxn],n,m,tot,num;
bool bridge[maxm];
void add(int x,int y)
{
ver[++tot] = y;
Next[tot] = head[x];
head[x] = tot;///
}
void tarjan(int x,int in_edge)
{
dfn[x] = low[x] = ++num;
for (int i = head[x];i;i = Next[i])
{
int y = ver[i];
if(!dfn[y])
{
tarjan(y,i);
low[x] = min(low[x],low[y]);
if(low[y] > dfn[x])
bridge[i] = bridge[i ^ 1] = 1;
}
else if(i != (in_edge ^ 1))
low[x] = min(low[x],dfn[y]);
}
}
int c[maxn],dcc;
void dfs(int x){
c[x] = dcc;
for (int i = head[x] ;i;i = Next[i])
{
int y = ver[i];
if(c[y] || bridge[i])
continue;
dfs(y);
}
}
int hc[maxn],vc[maxm],nc[maxm],tc;
void add_c(int x,int y)
{
vc[++tc] = y;
nc[tc] = hc[x];
hc[x] = tc;
}
int v[maxn],d[maxn],ans;
void dp(int x)
{
v[x] = 1;
for (int i = hc[x];i;i = nc[i])
{
int y = vc[i];
if(v[y])continue;
dp(y);
ans = max(ans,d[x]+d[y]+1);
d[x] = max(d[x],d[y] + 1);
}
}
void init()
{
#define memset(a,b) memset(a,b,sizeof(a))
memset(head,0);
memset(hc,0);
memset(d,0);
memset(c,0);
memset(v,0);
memset(dfn,0);
memset(bridge,0);
tc = tot = 1;
dcc = num = ans = 0;
}
int main()
{
while(scanf("%d%d",&n,&m) &&(n + m))
{
init();
int x,y;
for (int i = 1;i<=m;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for (int i = 1;i<=n;i++)
{
if(!dfn[i])
tarjan(i,0);
}
for (int i = 1;i<=n;i++)
{
if(!c[i])
{
++dcc;
dfs(i);
}
}
for (int i = 2;i<=tot;i++)
{
int x = ver[i ^ 1],y = ver[i];
if(c[x] == c[y])continue;
add_c(c[x],c[y]);
}
dp(1);
int sum = 0;
for (int i = 2;i < tot;i += 2)
{
if(bridge[i])
sum ++;
}
sum -= ans;
cout<<sum<<endl;
}
}
/*
7 7
1 2
1 3
1 4
1 5
2 3
2 6
3 7*/