http://acm.hdu.edu.cn/showproblem.php?pid=4612
4 4 1 2 1 3 1 4 2 3 0 0
0
/**
hdu4612 连通性,求树的直径,加一边求最少桥
题目大意:给定一个无向连通图加上一条边后所得到的图所含的桥的数目最少
解题思路:tarjan缩点边树,求出树的直径m,则原有桥数-m即为所求。
本题要注意考虑重边和注意求树的直径的方法(见代码注释)
*直径:;任意两个节点之间的最长距离
*/
#pragma comment(linker, "/STACK:1024000000,1024000000")///申请空间
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
const int maxn=200010;
const int maxm=2000014;
struct note
{
int v,next;
bool cut,chong_bian;
} edge[maxm];
int head[maxn],ip;
int n,m;
void init()
{
memset(head,-1,sizeof(head));
ip=0;
}
void addedge(int u,int v,bool chong_bian)
{
edge[ip].v=v,edge[ip].cut=false,edge[ip].chong_bian=chong_bian,edge[ip].next=head[u],head[u]=ip++;
}
int dfn[maxn],low[maxn],dex,inst[maxn],st[maxn],top,cnt,belong[maxn];
void tarjan(int u,int pre,bool ff)///ff代表重边
{
dfn[u]=low[u]=++dex;
st[top++]=u;
inst[u]=1;
for(int i=head[u]; i!=-1; i=edge[i].next)
{
int v=edge[i].v;
if(v==pre&&(!ff))continue;///与没有重边的区别
if(!dfn[v])
{
tarjan(v,u,edge[i].chong_bian);
if(low[u]>low[v])low[u]=low[v];
if(low[v]>dfn[u])
{
///bridge++;
edge[i].cut=true;
edge[i^1].cut=true;
}
}
else if(inst[v]&&dfn[v]<low[u])
{
low[u]=dfn[v];
}
}
if(dfn[u]==low[u])
{
cnt++;
int v;
do
{
v=st[--top];
inst[v]=0;
belong[v]=cnt;
}
while(v!=u);
}
}
vector <int> vec[maxn];
int dep[maxn];
void dfs(int u)///dfs求每个节点的深度
{
for(int i=0; i<vec[u].size(); i++)
{
int v=vec[u][i];
if(dep[v]!=-1)continue;
dep[v]=dep[u]+1;
dfs(v);
}
}
void solve()
{
memset(dfn,0,sizeof(dfn));
memset(inst,0,sizeof(inst));
cnt=dex=top=0;
tarjan(1,0,false);
for(int i=1;i<=cnt;i++)
vec[i].clear();
for(int u=1; u<=n; u++)
{
for(int i=head[u]; i!=-1; i=edge[i].next)
{
if(edge[i].cut)
{
int v=edge[i].v;
vec[belong[u]].push_back(belong[v]);
}
}
}
///=======求直径=========
memset(dep,-1,sizeof(dep));
dep[1]=0;
dfs(1);
int k=1;
for(int i=1; i<=cnt; i++)
{
if(dep[i]>dep[k])
k=i;
}
memset(dep,-1,sizeof(dep));
dep[k]=0;
dfs(k);
int ans=0;
for(int i=1; i<=cnt; i++)
{
ans=max(ans,dep[i]);
}
///=======================
printf("%d\n",cnt-1-ans);
}
struct note_
{
int x,y;
} node[maxm];
bool cmp(note_ a,note_ b)
{
if(a.x==b.x)
return a.y<b.y;
return a.x<b.x;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0)break;
for(int i=0; i<m; i++)
{
int u,v;
scanf("%d%d",&u,&v);
if(u==v)continue;
if(u>v)swap(u,v);
node[i].x=u;
node[i].y=v;
}
sort(node,node+m,cmp);
init();
for(int i=0; i<m; i++)
{
if(i==0||(node[i].x!=node[i-1].x||node[i].y!=node[i-1].y))
{
if(i<m-1&&node[i].x==node[i+1].x&&node[i].y==node[i+1].y)
{
addedge(node[i].x,node[i].y,true);
addedge(node[i].y,node[i].x,true);
}
else
{
addedge(node[i].x,node[i].y,false);
addedge(node[i].y,node[i].x,false);
}
}
}
solve();
}
return 0;
}
原文:http://blog.csdn.net/lvshubao1314/article/details/44040407