4 4 1 2 1 3 1 4 2 3 0 0
0
给定一个联通图,问加入一条边后,最少还余下多少个割边
分析:先求强连通分量个数num,然后缩点形成一棵树,再求树的直径cnt,答案就是num-1-cnt;
程序:
#pragma comment(linker, "/STACK:10240000000000,10240000000000") #include"stdio.h" #include"string.h" #include"stdlib.h" #include"stack" #include"iostream" #define M 201009 #define inf 99999999 using namespace std; stack<int>q; struct st { int u,v,w,next; }edge[M*10]; int head[M],use[M],t,dis[M][3],in[M],index,num,belong[M],dfn[M],low[M]; void init() { t=0; memset(head,-1,sizeof(head)); } void add(int u,int v,int w) { edge[t].u=u; edge[t].v=v; edge[t].w=w; edge[t].next=head[u]; head[u]=t++; } void tarjan(int u,int id) { dfn[u]=low[u]=++index; q.push(u); use[u]=1; int i; for(i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(i==(id^1))continue; if(!dfn[v]) { tarjan(v,i); low[u]=min(low[u],low[v]); } low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { int vv; num++; do { vv=q.top(); q.pop(); belong[vv]=num; use[vv]=0; }while(vv!=u); } } void dfs(int u) { use[u]=1; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(!use[v]) { dfs(v); //更新最大值和次大值 if(dis[u][0]<dis[v][0]+edge[i].w) { int tt=dis[u][0]; dis[u][0]=dis[v][0]+edge[i].w; dis[u][1]=tt; } else if(dis[u][1]<dis[v][0]+edge[i].w) dis[u][1]=dis[v][0]+edge[i].w; } } if(in[u]==1&&u!=1)//注意 dis[u][0]=dis[u][1]=0; } void solve(int n) { index=num=0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(use,0,sizeof(use)); memset(belong,0,sizeof(belong)); tarjan(1,-1); } int uu[M],vv[M]; int main() { int n,m,i; while(scanf("%d%d",&n,&m),m||n) { init(); while(m--) { int a,b; scanf("%d%d",&a,&b); add(a,b,1); add(b,a,1); } solve(n); int cnt=0; for(i=0;i<t;i+=2) { int u=edge[i].u; int v=edge[i].v; if(belong[u]!=belong[v]) { uu[cnt]=belong[u]; vv[cnt]=belong[v]; cnt++; } } init(); memset(in,0,sizeof(in)); memset(use,0,sizeof(use)); memset(dis,0,sizeof(dis)); for(i=0;i<cnt;i++) { //printf("%d %d\n",uu[i],vv[i]); add(uu[i],vv[i],1); add(vv[i],uu[i],1); in[uu[i]]++; in[vv[i]]++; } dfs(1); int ans=0; for(i=1;i<=num;i++) { if(ans<dis[i][0]+dis[i][1]) ans=dis[i][1]+dis[i][0]; } printf("%d\n",num-1-ans); } return 0; }