hdu4612 卡cin e-DCC缩点
/* 给定无向图,求加入一条边后最少剩下多少桥 */ #include<bits/stdc++.h> using namespace std; #define maxn 200005 #define maxm 1000005 struct Edge{int to,nxt,cut;}edge[maxm<<1],edge_c[maxm<<1]; int head[maxn],tot,head_c[maxn],tot_c,n,m,q; void addedge(int u,int v){ edge[tot].to=v;edge[tot].nxt=head[u];head[u]=tot++; edge[tot].cut=0; } void add_c(int u,int v){ edge_c[tot_c].to=v; edge_c[tot_c].nxt=head_c[u]; head_c[u]=tot_c++; } int dfn[maxn],low[maxn],ind,c[maxn],dcc; void tarjan(int u,int in_edge){ dfn[u]=low[u]=++ind; for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(!dfn[v]){ tarjan(v,i); low[u]=min(low[u],low[v]); if(dfn[u]<low[v]) edge[i].cut=edge[i^1].cut=1; } else if(i!=(in_edge^1)) low[u]=min(low[u],dfn[v]); } } void dfs1(int u){ c[u]=dcc; for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(c[v]||edge[i].cut)continue; dfs1(v); } } int dep[maxn],fa[maxn],flag[maxn];//flag[u]表示u上点的边使割边 void dfs2(int u,int pre,int deep){ dep[u]=deep;fa[u]=pre;flag[u]=1; for(int i=head_c[u];i!=-1;i=edge_c[i].nxt){ int v=edge_c[i].to; if(v==pre)continue; dfs2(v,u,deep+1); } } void init(){ memset(head,-1,sizeof head); memset(head_c,-1,sizeof head_c); memset(dep,0,sizeof dep); memset(fa,0,sizeof fa); memset(flag,0,sizeof flag); memset(c,0,sizeof c); memset(dfn,0,sizeof dfn); memset(low,0,sizeof low); tot=tot_c=ind=dcc=0; } int main(){ int tt=0; while(cin>>n>>m,n){ init(); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } tarjan(1,0); dcc=0;//染色 for(int i=1;i<=n;i++) if(!c[i]){ ++dcc; dfs1(i); } for(int i=0;i<tot;i++){//缩点 int v=edge[i].to,u=edge[i^1].to; if(c[u]==c[v])continue; add_c(c[u],c[v]); } int Max=-1,root=1; dfs2(root,0,0); for(int i=1;i<=dcc;i++) if(Max<dep[i]){ Max=dep[i]; root=i; } memset(dep,0,sizeof dep); dfs2(root,0,0); for(int i=1;i<=dcc;i++) Max=max(Max,dep[i]); cout<<dcc-1-Max<<endl; } return 0; }