求在给定图中添加一条边最多能是多少条桥消失。
双联通缩点,成为一棵树,然后求树的直径。
此图中两点之间可能会有重边,也按双联通,而不能按桥处理。其他的就没什么特别的。
对于要加入计算的重边,有下面两种解决变法,第一种比较好,也容易理解,就是用pre_num做标记,第一次不回头,第二次以上才可以回头递归。
第二种太过麻烦,就不说了,想看下代码的就略微看下,思路都差不多,一些方法细节而已。
代码一(后来加的,发现了好点的方法):
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cmath>
#include<map>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define rev(i,a,b) for(int i=(a);i>=(b);i--)
#define clr(a,x) memset(a,x,sizeof a)
#define INF 0x3f3f3f3f
typedef long long LL;
using namespace std;
const int maxn=200005;
const int maxm=2000005;
int first[maxn],ecnt,u[maxm],v[maxm],nex[maxm];
int low[maxn],dfn[maxn],stck[maxn],belong[maxn];
int indx,top,block;
bool ins[maxn],done[maxm];
int num[maxn];
int in[maxn],out[maxn];
int h[maxn];
int n,m;
int ecntt,firstt[maxn],uu[maxm],vv[maxm],nexx[maxm];
void tarjan(int s,int pre)
{
low[s]=dfn[s]=++indx;
stck[top++]=s;
ins[s]=1;
int pre_num=0;
for(int e=first[s];~e;e=nex[e])
{
if(v[e]==pre&&!pre_num)
{
pre_num++;
continue;
}
if(!dfn[v[e]])
{
tarjan(v[e],s);
low[s]=min(low[s],low[v[e]]);
}
else if(ins[v[e]])low[s]=min(low[s],dfn[v[e]]);
}
if(low[s]==dfn[s])
{
int v;
block++;
do
{
v=stck[--top];
ins[v]=false;
belong[v]=block;
}while(v!=s);
}
}
void solve(int n)
{
clr(dfn,0);
clr(ins,0);
clr(num,0);
indx=block=top=0;
for(int i=1;i<=n;i++)
if(!dfn[i])tarjan(1,0);
}
void add_(int a,int b)
{
u[ecnt]=a;
v[ecnt]=b;
nex[ecnt]=first[a];
first[a]=ecnt++;
}
void add__(int a,int b)
{
uu[ecntt]=a;
vv[ecntt]=b;
nexx[ecntt]=firstt[a];
firstt[a]=ecntt++;
}
void init()
{
ecnt=0;
clr(first,-1);
}
void suodian()
{
ecntt=0;clr(firstt,-1);
clr(in,0);
for(int e=0;e<ecnt;e++)
{
int a=belong[u[e]];
int b=belong[v[e]];
if(a!=b)add__(a,b),in[b]++;
}
}
void dfs(int s)
{
for(int e=firstt[s];~e;e=nexx[e])
{
if(h[vv[e]]!=-1)continue;
h[vv[e]]=h[s]+1;
dfs(vv[e]);
}
}
int main()
{
int a,b;
while(~scanf("%d%d",&n,&m)&&n+m)
{
init();
for(int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
if(a==b)continue;
add_(a,b);
add_(b,a);
}
solve(n);
suodian();
clr(h,-1);
h[1]=0;
dfs(1);
int k=1;
for(int i=1;i<=block;i++)
if(h[i]>h[k])k=i;
clr(h,-1);
h[k]=0;
dfs(k);
int ans=0;
for(int i=1;i<=block;i++)
ans=max(ans,h[i]);
printf("%d\n",block-1-ans);
}
return 0;
}
代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cmath>
#include<map>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define rev(i,a,b) for(int i=(a);i>=(b);i--)
#define clr(a,x) memset(a,x,sizeof a)
#define INF 0x3f3f3f3f
typedef long long LL;
using namespace std;
const int maxn=200005;
const int maxm=2000005;
struct node
{
int u,v;
bool operator<(const node &b)const
{
if(b.u!=u)return u<b.u;
return v<b.v;
}
}da[maxm/2];
int first[maxn],ecnt,u[maxm],v[maxm],nex[maxm];
bool pro[maxm];
int low[maxn],dfn[maxn],stck[maxn],belong[maxn];
int indx,top,block;
bool ins[maxn],done[maxm];
int num[maxn];
int in[maxn],out[maxn];
int h[maxn];
int n,m;
int ecntt,firstt[maxn],uu[maxm],vv[maxm],nexx[maxm];
void tarjan(int s,int pre,bool ff)
{
low[s]=dfn[s]=++indx;
stck[top++]=s;
ins[s]=1;
for(int e=first[s];~e;e=nex[e])
{
if(v[e]==pre&&!ff)continue;
if(!dfn[v[e]])
{
tarjan(v[e],s,pro[e]);
low[s]=min(low[s],low[v[e]]);
}
else if(ins[v[e]])low[s]=min(low[s],dfn[v[e]]);
}
if(low[s]==dfn[s])
{
int v;
block++;
do
{
v=stck[--top];
ins[v]=false;
belong[v]=block;
}while(v!=s);
}
}
void solve(int n)
{
clr(dfn,0);
clr(ins,0);
clr(num,0);
indx=block=top=0;
for(int i=1;i<=n;i++)
if(!dfn[i])tarjan(1,0,false);
}
void add_(int a,int b,bool d)
{
u[ecnt]=a;
v[ecnt]=b;
pro[ecnt]=d;
nex[ecnt]=first[a];
first[a]=ecnt++;
}
void add__(int a,int b)
{
uu[ecntt]=a;
vv[ecntt]=b;
nexx[ecntt]=firstt[a];
firstt[a]=ecntt++;
}
void init()
{
ecnt=0;
clr(first,-1);
}
void suodian()
{
ecntt=0;clr(firstt,-1);
clr(in,0);
for(int e=0;e<ecnt;e++)
{
int a=belong[u[e]];
int b=belong[v[e]];
if(a!=b)add__(a,b),in[b]++;
}
}
void dfs(int s)
{
for(int e=firstt[s];~e;e=nexx[e])
{
if(h[vv[e]]!=-1)continue;
h[vv[e]]=h[s]+1;
dfs(vv[e]);
}
}
int main()
{
int a,b;
while(~scanf("%d%d",&n,&m)&&n+m)
{
init();
for(int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
if(a==b)continue;
if(a>b)swap(a,b);
da[i].u=a;
da[i].v=b;
}
sort(da,da+m);
for(int i=0;i<m;i++)
{
if(i==0||da[i].u!=da[i-1].u||da[i].v!=da[i-1].v)
{
if(i<m-1&&(da[i].u==da[i+1].u&&da[i].v==da[i+1].v))
{
add_(da[i].u,da[i].v,true);
add_(da[i].v,da[i].u,true);
}
else
{
add_(da[i].u,da[i].v,false);
add_(da[i].v,da[i].u,false);
}
}
}
solve(n);
suodian();
clr(h,-1);
h[1]=0;
dfs(1);
int k=1;
for(int i=1;i<=block;i++)
if(h[i]>h[k])k=i;
clr(h,-1);
h[k]=0;
dfs(k);
int ans=0;
for(int i=1;i<=block;i++)
ans=max(ans,h[i]);
printf("%d\n",block-1-ans);
}
return 0;
}