题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4616
题目大意:
给你一个无向图,
问加上一条边之后,最少含有多少桥边。
算法:
加一条边的实质就是,在图上新增了一个环,并且把这个环上的所有点收缩到一个双联通分量里。
也就是说,原来在环上的桥边,加边之后都不再是桥边。
那么,我们先用双联通缩点,在缩点后的到的桥中找最长路径就可以了。
PS:注意一下这道题必须交c++不能交g++
代码如下:
#pragma comment(linker,"/STACK:102400000,102400000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #define INF 0x3f3f3f3f using namespace std; int head[200100],low[200100],dis[200100],d[200100],p[200100],pre[200100],cot,E,n,m; bool hash[2000100]; vector<int>mm[200100]; int maxl; struct { int u,v,nxt; } edge[2000100]; void addedge(int u,int v) { edge[E].u=u; edge[E].v=v; edge[E].nxt=head[u]; head[u]=E++; edge[E].u=v; edge[E].v=u; edge[E].nxt=head[v]; head[v]=E++; } int findr(int x) { if(p[x]<0)return x; return p[x]=findr(p[x]); } void reunion(int x,int y) { int px=findr(x); int py=findr(y); if(px!=py) p[px]=py; return; } void dfs(int u) { low[u]=dis[u]; for(int i=head[u]; i!=-1; i=edge[i].nxt) { hash[i]=1; int v=edge[i].v; if(dis[v]==-1) { pre[v]=u; dis[v]=cot++; dfs(v); low[u]=low[u]<low[v]?low[u]:low[v]; } else if(pre[u]!=v) { low[u]=low[u]<dis[v]?low[u]:dis[v]; } else if(!hash[i^1]) { low[u]=low[u]<dis[v]?low[u]:dis[v]; } } return; } int dp(int u, int dep) { int tmp,tmp1,tmp2; dis[u]=dep; tmp1=tmp2=0; for(int i=0; i<mm[u].size(); i++) { int v=mm[u][i]; if(dis[v]!=-1) { continue; } tmp=dp(v,dep+1)+1; if(tmp>=tmp1) { tmp2=tmp1; tmp1=tmp; } else if(tmp>tmp2) { tmp2=tmp; } } maxl=max(maxl,tmp1+tmp2); return tmp1; } int main() { while(scanf("%d%d",&n,&m),(n||m)) { E=0; memset(dis,-1,sizeof(dis)); memset(d,0,sizeof(d)); memset(head,-1,sizeof(head)); memset(hash,0,sizeof(hash)); memset(p,-1,sizeof(p)); while(m--) { int u,v; scanf("%d%d",&u,&v); addedge(u,v); } cot=0; dis[1]=cot++; dfs(1); memset(hash,0,sizeof(hash)); for(int i=0; i<E; i++) { if(pre[edge[i].v]==edge[i].u&&dis[edge[i].u]<low[edge[i].v]) { hash[i]=hash[i^1]=true; } } for(int i=1; i<=n; i++) { mm[i].clear(); } for(int i=0; i<E; i+=2) { if(!hash[i]) { reunion(edge[i].u,edge[i].v); } } int ans=0; for(int i=0; i<E; i+=2) { if(hash[i]) { int u=findr(edge[i].u); int v=findr(edge[i].v); mm[u].push_back(v); mm[v].push_back(u); ans++; } } memset(dis,-1,sizeof(dis)); maxl=0; for(int i=1; i<=n; i++) { if(mm[i].size()&&dis[i]==-1) { maxl=max(maxl,dp(i,0)); } } printf("%d\n",ans-maxl); } return 0; }