hdu 4612 Warm up(无向图Tarjan+树的直径)
题意:有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+树的直径)的更多相关文章
- 【HDU 4612 Warm up】BCC 树的直径
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4612 题意:一个包含n个节点m条边的无向连通图(无自环,可能有重边).求添加一条边后最少剩余的桥的数 ...
- Hdu 4612 Warm up (双连通分支+树的直径)
题目链接: Hdu 4612 Warm up 题目描述: 给一个无向连通图,问加上一条边后,桥的数目最少会有几个? 解题思路: 题目描述很清楚,题目也很裸,就是一眼看穿怎么做的,先求出来双连通分量,然 ...
- HDU 4612——Warm up——————【边双连通分量、树的直径】
Warm up Time Limit:5000MS Memory Limit:65535KB 64bit IO Format:%I64d & %I64u Submit Stat ...
- hdu 4612 Warm up 有重边缩点+树的直径
题目链接 Warm up Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Tot ...
- HDU 4612 Warm up —— (缩点 + 求树的直径)
题意:一个无向图,问建立一条新边以后桥的最小数量. 分析:缩点以后,找出新图的树的直径,将这两点连接即可. 但是题目有个note:两点之间可能有重边!而用普通的vector保存边的话,用v!=fa的话 ...
- HDU 4612 Warm up(双连通分量缩点+求树的直径)
思路:强连通分量缩点,建立一颗新的树,然后求树的最长直径,然后加上一条边能够去掉的桥数,就是直径的长度. 树的直径长度的求法:两次bfs可以求,第一次随便找一个点u,然后进行bfs搜到的最后一个点v, ...
- HDU 4612 Warm up (边双连通分量+缩点+树的直径)
<题目链接> 题目大意:给出一个连通图,问你在这个连通图上加一条边,使该连通图的桥的数量最小,输出最少的桥的数量. 解题分析: 首先,通过Tarjan缩点,将该图缩成一颗树,树上的每个节点 ...
- hdu 4612 Warm up
http://acm.hdu.edu.cn/showproblem.php?pid=4612 将原图进行缩点 变成一个树 树上每条边都是一个桥 然后加一条边要加在树的直径两端才最优 代码: #incl ...
- 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 ...
随机推荐
- (原)Opencv中直方图均衡和图像动态范围拉伸的代码
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5102032.html 参考网址: http://blog.csdn.net/abcjennifer/a ...
- Ecstore中如何调用发起Ajax请求
Ecstore的JS框架使用了mootools,所以ajax调用也使用mootools中的Request组件. 语法: var myRequest = new Request([options]); ...
- yii2安装与初始化-Yii2学习笔记(一)
一.安装项目: 使用composer下载安装yii2 advanced安装包: composer create-project yiisoft/yii2-app-advanced advanced(自 ...
- Qt仿Android带特效的数字时钟源码分析(滑动,翻页,旋转效果)
这个数字时钟的源码可以在Qt Demo中找到,风格是仿Android的,不过该Demo中含有三种动画效果(鉴于本人未曾用过Android的系统,因此不知道Android的数字时钟是否也含有这三种效果) ...
- 《Programming WPF》翻译 目录
原文:<Programming WPF>翻译 目录 注:第1.2章我只做了笔记,没有翻译,请大家阅读时注意. 还有就是,这本书的英文版本下载:[O'Reilly] Programming ...
- 2014第2周三Web安全学习
2014第2周三Web安全学习 先记录下自己关于json和xml作为数据传递媒介的差异:在写一个java方法时我将正确结果返回的对象转成json返回,将错误结果根据不同原因以xml形式返回,同事看后有 ...
- bzoj1632 [Usaco2007 Feb]Lilypad Pond
Description Farmer John 建造了一个美丽的池塘,用于让他的牛们审美和锻炼.这个长方形的池子被分割成了 M 行和 N 列( 1 ≤ M ≤ 30 ; 1 ≤ N ≤ 30 ) 正方 ...
- python使用post登陆电子科大信息门户并保存登陆后页面
python使用post登陆电子科大信息门户并保存登陆后页面 作者:vpoet mail:vpoet_sir@163.com #coding=utf-8 import HTMLParser impor ...
- HDOJ-1012 u Calculate e(水)
http://acm.hdu.edu.cn/showproblem.php?pid=1012 简单套公式 # include <stdio.h> double Factorial(doub ...
- 【LeetCode练习题】Unique Paths II
Unique Paths II Follow up for "Unique Paths": Now consider if some obstacles are added to ...