#pragma comment(linker,"/STACK:102400000,102400000")
#include <iostream>
#include <queue>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 200100;
const int maxm = 2000100;
struct node{
int v,next;
}edge[maxm];
struct Bridge
{
int u,v;
}bridge[maxm];
int head[maxn],vis[maxm],fa[maxn],dfn[maxn],low[maxn],stack[maxn],in[maxn];
int id,time,num,total,top,ans;
void add_edge(int u,int v)
{
edge[id].v = v;edge[id].next = head[u],head[u] = id++;
edge[id].v = u;edge[id].next = head[v],head[v] = id++;
}
int min(int x,int y)
{
return x < y ? x : y;
}
void tarjan(int u)
{//无向图找桥并缩点
low[u] = dfn[u] = ++time;
stack[top++] = u;
for(int id = head[u] ; id != -1; id = edge[id].next)
{
int v =edge[id].v;
if(vis[id])continue;
vis[id] = vis[id^1] = 1;
if( !dfn[v] )
{
tarjan(v);
low[u] = min(low[u],low[v]);
if( low[v] > dfn[u])//u经过v不能回到u,则u与v之间存在桥
{
bridge[total].u = u;
bridge[total++].v = v;
}
}
low[u] = min(low[u],dfn[v]);
}
if(low[u] == dfn[u])
{//对连通分量进行缩点
num++;
int t;
do{
t = stack[--top];
fa[t] = num;
}while( t != u);
}
}
vector<int>g[maxn]; int dfs(int u)
{//求树的最大直径
vis[u]=1;
int i,j,temp=0,Max=0,lMax=0;//Max为以u为根,u到的最远的叶子节点的距离,lMax为次最远距离
for(i = 0; i < g[u].size() ; i++ ){
int v = g[u][i];
if(vis[v])continue;
temp=dfs(v);
if(temp+1>=Max){
lMax=Max;
Max=temp+1;
}
else
if(temp+1>lMax)
lMax=temp+1;
if(Max+lMax>ans)
ans=Max+lMax;
}
return Max;
} int max_len()
{//求树的最大直径
int res = 0;
memset(vis,0,sizeof(vis));
queue<int>que;
que.push(1);
vis[1] = 1;
int tmp;
while( !que.empty())
{
int u = que.front();
que.pop();
tmp = u;
for( int i = 0 ; i < g[u].size(); i++)
{
int v = g[u][i];
if( vis[v] )continue;
vis[v] = 1;
que.push(v);
}
} queue<pair<int,int> >que1;
memset(vis,0,sizeof(vis));
que1.push(make_pair(tmp,0));
pair<int,int>x,y;
vis[tmp] = 1;
while( !que1.empty())
{
x = que1.front();
que1.pop();
for(int i = 0; i < g[x.first].size() ; i++)
{
int v = g[x.first][i];
if( vis[v] )continue;
vis[v] = 1;
que1.push(make_pair(v,x.second+1));
res = res > x.second ? res : x.second + 1;
}
}
return res;
}
int main()
{
int n,m,u,v;
int i;
// freopen("in.txt","r",stdin);
while( ~scanf("%d%d",&n,&m) && n+m)
{
id = 0;
memset(head,-1,sizeof(head));
while( m-- )
{
scanf("%d%d",&u,&v);
add_edge(u,v);
}
total = num = 0;
memset(dfn,0,sizeof(dfn));
memset(fa,-1,sizeof(fa));
memset(vis,0,sizeof(vis));
for(i = 1; i <= n; i++)//可以处理不连通的无向图,如果连通只需要一次即可
{
if( !dfn[i] )
{
top = time = 1;
tarjan(i);
//num++;
//for( int j = 1; j <= n; j++) //特殊处理顶点的连通块
// if( dfn[j] && fa[j] == -1)fa[j] = num;
}
}
//for( i = 1; i <= n; i++)cout << fa[i] << endl;
for(i = 1; i <= n;i++)g[i].clear();
int x,y;
//建树
// cout << total << endl;
for( i = 0 ; i < total; i++)
{
x = fa[bridge[i].u];
y = fa[bridge[i].v];
//cout << x << " " << y << endl;
g[x].push_back(y);
g[y].push_back(x);
}
memset(vis,0,sizeof(vis));
ans = 0;
dfs(1);
printf("%d\n",total - ans );
}
return 0;
}

  

  

hdu 4612 无向图连通分量缩点,然后求树的最大直径的更多相关文章

  1. hdu 4612 双联通缩点+树形dp

    #pragma comment(linker,"/STACK:102400000,102400000")//总是爆栈加上这个就么么哒了 #include<stdio.h> ...

  2. HDU-4612 Warm up,tarjan求桥缩点再求树的直径!注意重边

    Warm up 虽然网上题解这么多,感觉写下来并不是跟别人竞争访问量的,而是证明自己从前努力过,以后回头复习参考! 题意:n个点由m条无向边连接,求加一条边后桥的最少数量. 思路:如标题,tarjan ...

  3. HDU4612+Tarjan缩点+BFS求树的直径

    tarjan+缩点+树的直径题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少.先tarjan缩点,再在这棵树上求直径.加的边即是连接这条直径的两端. /* tarjan ...

  4. HDU 4607 Park Visit 两次DFS求树直径

    两次DFS求树直径方法见 这里. 这里的直径是指最长链包含的节点个数,而上一题是指最长链的路径权值之和,注意区分. K <= R: ans = K − 1; K > R:   ans = ...

  5. HDU 4607 Park Visit 树的最大直径

    题意: 莱克尔和她的朋友到公园玩,公园很大也很漂亮.公园包含n个景点通过n-1条边相连.克莱尔太累了,所以不能去参观所有点景点. 经过深思熟虑,她决定只访问其中的k个景点.她拿出地图发现所有景点的入口 ...

  6. HDU 4612 Warm up(双连通分量缩点+求树的直径)

    思路:强连通分量缩点,建立一颗新的树,然后求树的最长直径,然后加上一条边能够去掉的桥数,就是直径的长度. 树的直径长度的求法:两次bfs可以求,第一次随便找一个点u,然后进行bfs搜到的最后一个点v, ...

  7. hdoj 4612 Warm up【双连通分量求桥&&缩点建新图求树的直径】

    Warm up Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Su ...

  8. HDU 4612 Warm up (边双连通分量+缩点+树的直径)

    <题目链接> 题目大意:给出一个连通图,问你在这个连通图上加一条边,使该连通图的桥的数量最小,输出最少的桥的数量. 解题分析: 首先,通过Tarjan缩点,将该图缩成一颗树,树上的每个节点 ...

  9. HDU 4612——Warm up——————【边双连通分量、树的直径】

    Warm up Time Limit:5000MS     Memory Limit:65535KB     64bit IO Format:%I64d & %I64u Submit Stat ...

随机推荐

  1. CDN绕过姿势小结

    公司的各业务主站都挂了CDN,总结一波CDN绕过技巧. 什么是CDN CDN的全称是Content Delivery Network,即内容分发网络. 其基本思路是尽可能避开互联网上有可能影响数据传输 ...

  2. H3C模拟器实验之网络地址转换

    网络拓扑图 NOTE:各个设备的基本配置在拓扑图上已经标明(需要注意的是RTB的出接口也需要配置IP,但是使用ping -a 10.1.1.1 202.117.144.1 ping不通,这点不是很理解 ...

  3. ieda控制台缓冲区限制问题

    一.现象 控制台输出数据若超过默认值时,将从后向前取默认值大小数据(1024) 二.解决方案 1.配置文件(idea安装目录/bin/idea.properties) 2.找到该栏:idea.cycl ...

  4. SQL Labs刷题补坑记录(less31-less53)

    LESS31: 双引号直接报错,那么肯定可以报错注入,并且也过滤了一些东西,^异或没有过滤,异或真香 -1" and (if(length(database())=8,1,0)) and & ...

  5. Centos安装git并配置ssh

    1.下载git安装包 git-2.9.4.tar.gz 2.解压 tar -xzvf git-2.9.4.tar.gz 3.修改解压后的文件名 mv git-2.9.4 git 4.安装git依赖的库 ...

  6. HTML5 Device Access (设备访问)

    camera api (含图片预览) 参考地址 主要为利用input type=file, accept="image/*" 进行处理 图片预览方式(两种) const file ...

  7. android——卡片式布局

    一.CardView <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk ...

  8. Oauth2认证模式之授权码模式实现

    Oauth2认证模式之授权码模式(authorization code) 本示例实现了Oauth2之授权码模式,授权码模式(authorization code)是功能最完整.流程最严密的授权模式.它 ...

  9. Transformation HDU - 4578(线段树——懒惰标记的妙用)

    Yuanfang is puzzled with the question below: There are n integers, a 1, a 2, …, a n. The initial val ...

  10. 【数据结构】线段树(Segment Tree)

    假设我们现在拿到了一个非常大的数组,对于这个数组里面的数字要反复不断地做两个操作. 1.(query)随机在这个数组中选一个区间,求出这个区间所有数的和. 2.(update)不断地随机修改这个数组中 ...