做这题是噩梦的一天….
先用tarjan缩点求出各个强联通块并且找出桥数
要求连一条边后得到的剩余最小的桥
所以要找一条路能达到的最深的路径
则ans = bridge - maxdeep
先用spfa的dfs找出能达到的最大深度
然后从最大深度开始搜索最大的深度
最后相减就是答案
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 200005;
const int maxm = 1000005;
int n, m, tol, top, cnt;
int maxdeep, pos;
int bridge;
int stacksize;
struct Node {
int v;
int next;
bool vis;
};
Node edge[4 * maxn];
Node node[2 * maxm];
bool vis[maxn];
int dfn[maxn];
int low[maxn];
int point[maxn];
int stack[maxn];
int head[maxn];
int head2[maxn];
void init() {
tol = cnt = top = stacksize = 0;
bridge = 0;
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(head, -1, sizeof(head));
memset(vis, false, sizeof(vis));
memset(point, 0, sizeof(point));
}
void addnode(int u, int v) {
node[tol].v = v;
node[tol].vis = false;
node[tol].next = head[u];
head[u] = tol++;
}
void addedge(int u, int v) {
edge[tol].v = v;
edge[tol].next = head[u];
head[u] = tol++;
}
void dfs(int u) {
int v;
low[u] = dfn[u] = ++cnt;
vis[u] = true;
stack[stacksize++] = u;
for(int i=head[u]; i!=-1; i=node[i].next) {
v=node[i].v;
if(node[i].vis)
continue;
node[i].vis = node[i^1].vis = true;
if(!dfn[v]) {
dfs(v);
low[u] = min(low[u],low[v]);
if(dfn[u] < low[v])
bridge++;
} else if(vis[v]) {
low[u] = min(low[u], dfn[v]);
}
}
if(dfn[u] == low[u]) {
top++;
int v;
do {
v = stack[--stacksize];
vis[v] = false;
point[v] = top;
} while(v != u);
}
}
void tarjan() {
for(int u=1; u<=n; u++) {
if(!dfn[u]) {
dfs(u);
}
}
}
void dfs2(int u, int deep) {
vis[u] = true;
if(deep > maxdeep) {
maxdeep = deep;
pos = u;
}
for(int i=head[u]; i!=-1; i=edge[i].next) {
int v = edge[i].v;
if(!vis[v]) {
dfs2(v, deep+1);
}
}
}
int main() {
while(scanf("%d%d",&n, &m) != EOF) {
if(n==0 && m==0)
break;
init();
for(int i=1; i<=m; i++) {
int u, v;
scanf("%d%d", &u, &v);
if(u == v)
continue;
addnode(u, v);
addnode(v, u);
}
tarjan();
memcpy(head2, head, sizeof(head));
memset(head, -1, sizeof(head));
tol = 0;
for(int u=1; u<=n; u++) {
for(int i=head2[u]; i!=-1; i=node[i].next) {
int v = node[i].v;
if(point[u] != point[v]) {
addedge(point[u], point[v]);
addedge(point[v], point[u]);
}
}
}
// for(int i=0; i<tol; i++)
// printf("%d %d\n",head[i]);
maxdeep = pos = 0;
memset(vis, false, sizeof(vis));
vis[1] = true;
dfs2(1, 0);
memset(vis, false, sizeof(vis));
maxdeep = 0;
vis[pos] = true;
dfs2(pos, 0);
int ans = bridge - maxdeep;
printf("%d\n", ans);
}
return 0;
}