题意:有N个点,M条边(有重边)的无向图,这样图中会可能有桥,问加一条边后,使桥最少,求该桥树。

思路:这个标准想法很好想到,缩点后,求出图中的桥的个数,然后重建图必为树,求出树的最长直径,在该直径的两端点连一边,则图中的桥会最少。

从这题中学到两点,所以写一下解题报告。

1.官方说judge的栈小,得手动增栈 #pragma comment(linker,"/STACK:102400000,102400000") 以前没见过,算是学习了。

2.对改正了对Tarjan算法的一个错误理解,以前看某人博客说,无向图中,Tarjan后low值相等的点属于同一块,以前这样判断过,也过了挺多题。但跟别人讨论后发现是错的。。。。。

3.以前没用Tarjan写过无向图,不懂正向边访问过,标志反向边,这次学习了。

//937MS    41304K
#pragma comment(linker, "/STACK:102400000,102400000")
#include
#include
const int VM = 200005;
const int EM = 1000005; struct Edeg
{
int to,nxt,vis;
}edge[EM<<1],tree[EM<<1]; int head[VM],vis[VM],thead[VM];
int dfn[VM],low[VM],stack[VM],belong[VM];
int ep,bridge,son,maxn,src,n,cnt,scc,top; int max (int a,int b)
{
return a > b ? a : b;
}
int min(int a ,int b)
{
return a > b ? b : a;
}
void addedge (int cu,int cv)
{
edge[ep].to = cv;
edge[ep].vis = 0;
edge[ep].nxt = head[cu];
head[cu] = ep ++;
edge[ep].to = cu;
edge[ep].vis = 0;
edge[ep].nxt = head[cv];
head[cv] = ep ++;
}
void Buildtree(int cu,int cv)
{
tree[son].to = cv;
tree[son].nxt = thead[cu];
thead[cu] = son ++;
}
void Tarjan (int u)
{
int v;
vis[u] = 1;
dfn[u] = low[u] = ++cnt;
stack[top++] = u;
for (int i = head[u];i != -1;i = edge[i].nxt)
{
v = edge[i].to;
if (edge[i].vis) continue; //
edge[i].vis = edge[i^1].vis = 1; //正向边访问过了,反向边得标志,否则两点会成一块。
if (vis[v] == 1)
low[u] = min(low[u],dfn[v]);
if (!vis[v])
{
Tarjan (v);
low[u] = min(low[u],low[v]);
if (low[v] > dfn[u])
bridge ++;
}
}
if (dfn[u] == low[u])
{
++scc;
do{
v = stack[--top];
vis[v] = 0;
belong[v] = scc;
}while (u != v);
}
}
void BFS(int u)
{
int que[VM+100];
int front ,rear,i,v;
front = rear = 0;
memset (vis,0,sizeof(vis));
que[rear++] = u;
vis[u] = 1;
while (front != rear)
{
u = que[front ++];
front = front % (n+1);
for (i = thead[u];i != -1;i = tree[i].nxt)
{
v = tree[i].to;
if (vis[v]) continue;
vis[v] = 1;
que[rear++] = v;
rear = rear%(n+1);
}
}
src = que[--rear];//求出其中一个端点
}
void DFS (int u,int dep)
{
maxn = max (maxn,dep);
vis[u] = 1;
for (int i = thead[u]; i != -1; i = tree[i].nxt)
{
int v = tree[i].to;
if (!vis[v])
DFS (v,dep+1);
}
}
void solve()
{
int u,v;
memset (vis,0,sizeof(vis));
cnt = bridge = scc = top = 0;
Tarjan (1);
memset (thead,-1,sizeof(thead));
son = 0;
for (u = 1;u <= n;u ++) //重构图
for (int i = head[u];i != -1;i = edge[i].nxt)
{
v = edge[i].to;
if (belong[u]!=belong[v])
{
Buildtree (belong[u],belong[v]);
Buildtree (belong[v],belong[u]);
}
}
maxn = 0; //最长直径
BFS(1); //求树直径的一个端点
memset (vis,0,sizeof(vis));
DFS(src,0); //求树的最长直径
printf ("%d\n",bridge-maxn);
} int main ()
{
#ifdef LOCAL
freopen ("in.txt","r",stdin);
#endif
int m,u,v;
while (~scanf ("%d%d",&n,&m))
{
if (n == 0&&m == 0)
break;
memset (head,-1,sizeof(head));
ep = 0;
while (m --)
{
scanf ("%d%d",&u,&v);
addedge (u,v);
}
solve();
}
return 0;
}

hdu 4612 Warm up(无向图Tarjan+树的直径)的更多相关文章

  1. 【HDU 4612 Warm up】BCC 树的直径

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4612 题意:一个包含n个节点m条边的无向连通图(无自环,可能有重边).求添加一条边后最少剩余的桥的数 ...

  2. Hdu 4612 Warm up (双连通分支+树的直径)

    题目链接: Hdu 4612 Warm up 题目描述: 给一个无向连通图,问加上一条边后,桥的数目最少会有几个? 解题思路: 题目描述很清楚,题目也很裸,就是一眼看穿怎么做的,先求出来双连通分量,然 ...

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

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

  4. hdu 4612 Warm up 有重边缩点+树的直径

    题目链接 Warm up Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Tot ...

  5. HDU 4612 Warm up —— (缩点 + 求树的直径)

    题意:一个无向图,问建立一条新边以后桥的最小数量. 分析:缩点以后,找出新图的树的直径,将这两点连接即可. 但是题目有个note:两点之间可能有重边!而用普通的vector保存边的话,用v!=fa的话 ...

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

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

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

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

  8. hdu 4612 Warm up

    http://acm.hdu.edu.cn/showproblem.php?pid=4612 将原图进行缩点 变成一个树 树上每条边都是一个桥 然后加一条边要加在树的直径两端才最优 代码: #incl ...

  9. HDU 4612 Warm up(2013多校2 1002 双连通分量)

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

随机推荐

  1. (原)Opencv中直方图均衡和图像动态范围拉伸的代码

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5102032.html 参考网址: http://blog.csdn.net/abcjennifer/a ...

  2. Ecstore中如何调用发起Ajax请求

    Ecstore的JS框架使用了mootools,所以ajax调用也使用mootools中的Request组件. 语法: var myRequest = new Request([options]); ...

  3. yii2安装与初始化-Yii2学习笔记(一)

    一.安装项目: 使用composer下载安装yii2 advanced安装包: composer create-project yiisoft/yii2-app-advanced advanced(自 ...

  4. Qt仿Android带特效的数字时钟源码分析(滑动,翻页,旋转效果)

    这个数字时钟的源码可以在Qt Demo中找到,风格是仿Android的,不过该Demo中含有三种动画效果(鉴于本人未曾用过Android的系统,因此不知道Android的数字时钟是否也含有这三种效果) ...

  5. 《Programming WPF》翻译 目录

    原文:<Programming WPF>翻译 目录 注:第1.2章我只做了笔记,没有翻译,请大家阅读时注意. 还有就是,这本书的英文版本下载:[O'Reilly] Programming ...

  6. 2014第2周三Web安全学习

    2014第2周三Web安全学习 先记录下自己关于json和xml作为数据传递媒介的差异:在写一个java方法时我将正确结果返回的对象转成json返回,将错误结果根据不同原因以xml形式返回,同事看后有 ...

  7. bzoj1632 [Usaco2007 Feb]Lilypad Pond

    Description Farmer John 建造了一个美丽的池塘,用于让他的牛们审美和锻炼.这个长方形的池子被分割成了 M 行和 N 列( 1 ≤ M ≤ 30 ; 1 ≤ N ≤ 30 ) 正方 ...

  8. python使用post登陆电子科大信息门户并保存登陆后页面

    python使用post登陆电子科大信息门户并保存登陆后页面 作者:vpoet mail:vpoet_sir@163.com #coding=utf-8 import HTMLParser impor ...

  9. HDOJ-1012 u Calculate e(水)

    http://acm.hdu.edu.cn/showproblem.php?pid=1012 简单套公式 # include <stdio.h> double Factorial(doub ...

  10. 【LeetCode练习题】Unique Paths II

    Unique Paths II Follow up for "Unique Paths": Now consider if some obstacles are added to ...