题意:有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. CSS属性值定义语法中的符号说名

    我们通常看到一个CSS语法,总是有很多符号在其中,这些符号是什么鬼呢,且看下面道来 这些符号可以大致分为2类:分组类与数量类. 1.分组类,就是分成一堆一堆啦: 符号 名称 描述 示例   并置 各部 ...

  2. uva 230 Borrowers(摘)<vector>"结构体“ 膜拜!

    I mean your borrowers of books--those mutilators of collections, spoilers of the symmetry of shelves ...

  3. Qt调用外部程序QProcess通信

    mainwindow.cpp文件: -------------------------------- #include "mainwindow.h" #include " ...

  4. java中的native关键字

    参照下面的链接http://blog.163.com/yueyemaitian@126/blog/static/21475796200701491621267/

  5. jquery的使用 超级快速入门 熟练使用

    如何使用jquery,首先需要引入jquery的js库文件,可以是免费的cdn资源,也可以是本地下载的资源 使用方法:$(function(){                  这里面写你要执行的代 ...

  6. PK投票效果

    /** *createTime:2015-07-21 *updateTime:2015-06-22 *author:刘俊 *Description:PK投票 *phone:13469119119 ** ...

  7. 数据挖掘(data mining),机器学习(machine learning),和人工智能(AI)的区别是什么? 数据科学(data science)和商业分析(business analytics)之间有什么关系?

    本来我以为不需要解释这个问题的,到底数据挖掘(data mining),机器学习(machine learning),和人工智能(AI)有什么区别,但是前几天因为有个学弟问我,我想了想发现我竟然也回答 ...

  8. c#一个分页控件的例子

    一.首先下载一个dll,地址:http://pan.baidu.com/share/link?shareid=1628211605&uk=1342867987 二.添加到项目中 三.添加引用 ...

  9. JavaSctipr 兼容、技巧、牛角尖

    关于JavaSctipt的兼容性,最懒的办法就是用jQuery的工具函数.尽量不要用那些什么ECMAScript之类的函数,因为很多浏览器都会报找不到函数的错误.下面列出一些在开发过程中碰到过的jav ...

  10. Java Socket 简单梳理

    Sockets let you send raw streams of bytes back and forth between two computers, giving you fairly lo ...