Warm up

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)

Total Submission(s): 3160    Accepted Submission(s): 718

Problem Description
  N planets are connected by M bidirectional channels that allow instant transportation. It's always possible to travel between any two planets through these channels.

  If we can isolate some planets from others by breaking only one channel , the channel is called a bridge of the transportation system.

People don't like to be isolated. So they ask what's the minimal number of bridges they can have if they decide to build a new channel.

  Note that there could be more than one channel between two planets.
 
Input
  The input contains multiple cases.

  Each case starts with two positive integers N and M , indicating the number of planets and the number of channels.

  (2<=N<=200000, 1<=M<=1000000)

  Next M lines each contains two positive integers A and B, indicating a channel between planet A and B in the system. Planets are numbered by 1..N.

  A line with two integers '0' terminates the input.
 
Output
  For each case, output the minimal number of bridges after building a new channel in a line.
 
Sample Input
4 4
1 2
1 3
1 4
2 3
0 0
 
Sample Output
0

题意:求出给定图中所有桥的数量,减去缩点后的最长链,即为题中所求答案(实际不用缩点也可求)

思路参考于:http://blog.csdn.net/qq172108805/article/details/9564705

#include "stdio.h"   //用到双连通分量和树形dp的思想
#include "string.h"
#pragma comment(linker,"/STACK:102400000,102400000") //手动扩大栈区(不扩栈会运行错误) #define N 201000
#define M 1001000 struct node
{
int x,y;
bool visit; //标记该边是否走过
int next;
}edge[4*M];
int idx,head[N]; inline int MIN(int a,int b){ return a<b?a:b; } void Init()
{
idx=0;
memset(head,-1,sizeof(head));
}
void Add(int x,int y)
{
edge[idx].x = x;
edge[idx].y = y;
edge[idx].visit = false; //开始时所有边都未走过
edge[idx].next = head[x];
head[x] = idx++;
} int n,m;
int sum,temp;
int low[N],dfn[N],time;
int dp1[N],dp2[N]; void DFS(int x)
{
int i,y;
dp1[x] = dp2[x] = 0;
low[x] = dfn[x] = ++time;
for(i=head[x]; i!=-1; i=edge[i].next)
{
if(edge[i].visit) continue;
y = edge[i].y;
edge[i].visit = edge[i^1].visit = true;
if(!dfn[y]) //点y未被访问过
{
DFS(y);
low[x] = MIN(low[x],low[y]);
if(low[y] > dfn[x])
sum++; //当前边为桥,sum++
temp = dp1[y];
if(low[y] > dfn[x])
temp++;
if(temp > dp1[x])
{
dp2[x] = dp1[x];
dp1[x] = temp;
}
else if(temp > dp2[x])
dp2[x] = temp;
}
else
low[x] = MIN(low[x],dfn[y]);
}
} int main()
{
int i;
int x,y;
while(scanf("%d %d",&n,&m),n||m)
{
Init();
for(i=0; i<m; ++i)
{
scanf("%d %d",&x,&y);
Add(x,y);
Add(y,x);
}
sum = 0; //统计图中桥的条数
time = 1;
memset(dfn,0,sizeof(dfn));
DFS(1);
int dist=0; //记录图的双连通分量缩点后的最长直径(最长的桥的长度)(实际不用处理缩点)
for(i=1; i<=n; ++i)
{
if(dist<dp1[i]+dp2[i]) //dp1[i]+dp2[i]为经过点i的最长路径的长度
dist = dp1[i]+dp2[i];
}
printf("%d\n",sum - dist);//所有桥的条数减最长路径的桥数,即为答案
}
return 0;
}

hdu 4612 Warm up 双连通+树形dp思想的更多相关文章

  1. hdu 4612 Warm up 双连通缩点+树的直径

    首先双连通缩点建立新图(顺带求原图的总的桥数,事实上因为原图是一个强连通图,所以桥就等于缩点后的边) 此时得到的图类似树结构,对于新图求一次直径,也就是最长链. 我们新建的边就一定是连接这条最长链的首 ...

  2. HDU 2242 考研路茫茫—空调教室 (边双连通+树形DP)

    <题目链接> 题目大意: 给定一个连通图,每个点有点权,现在需要删除一条边,使得整张图分成两个连通块,问你删除这条边后,两联通块点权值和差值最小是多少. 解题分析: 删除一条边,使原连通图 ...

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

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

  4. HDU 2242 考研路茫茫——空调教室(边双连通分量+树形dp+重边标号)

    http://acm.hdu.edu.cn/showproblem.php?pid=2242 题意: 思路:首先求一下双连通分量,如果只有一个双连通分量,那么无论断哪根管子,图还是连通的. 最后只需要 ...

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

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

  6. 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 ...

  7. HDU 5739 Fantasia 双连通分量 树形DP

    题意: 给出一个无向图,每个顶点有一个权值\(w\),一个连通分量的权值为各个顶点的权值的乘积,一个图的权值为所有连通分量权值之和. 设删除顶点\(i\)后的图\(G_i\)的权值为\(z_i\),求 ...

  8. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  9. HDU 1520.Anniversary party 基础的树形dp

    Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

随机推荐

  1. 【C++】第1章 在VS2015中用C++编写控制台应用程序

    分类:C++.VS2015 创建日期:2016-06-12 一.简介 看到不少人至今还在用VC 6.0开发工具学习C++,其实VC 6.0开发工具早就被淘汰了.这里仅介绍学习C++时推荐使用的两种开发 ...

  2. 验证控件插图扩展控件ValidatorCalloutExtender(用于扩展验证控件)和TextBoxWatermarkExtender

    <asp:ScriptManager ID="ScriptManager1" runat="server">  </asp:ScriptMan ...

  3. [PE结构分析] 7.相对虚拟地址(RVA)和文件偏移间的转换

    RVA是相对虚拟地址(Relative Virtual Address)的缩写.RVA是当PE 文件被装载到内存中后,某个数据位置相对于文件头的偏移量. 例如:导入表的位置和大小可以从PE文件头中IM ...

  4. 解决My eclipse 工程发布时端口占用问题

    如果运行后如图的错,需要进行如下操作来解决: a:打开cmd,输入netstat -ano 找到本地地址为8080的最后一项的数字,这个数字就是端口号. b:再输入taskkill /t /pid 端 ...

  5. 第三章--Win32程序的执行单元(部分概念及代码讲解)(上 -- 多线程)

    学习<Windows程序设计>记录 概念贴士: 1. 线程描述了进程内代码的执行路径. 2. _stdcall是新标准C/C++函数的调用方法.从底层来说,使用这种调用方法参数的进栈顺序和 ...

  6. Scala on Visual Studio Code

    Download and install Scala Download a scala installation package from here. Then install it. Linux s ...

  7. php学习笔记:利用递归实现删除文件目录

    直接删除目录,如果是空目录是可以删除,如果不是空目录,这时候只能先删除目录里面的文件,然后再删除目录.我封装了个删除函数,然后直接调用这个函数.喜欢的可以直接拿去用,编码是gbk的,使用时候注意下编码 ...

  8. linux shell 编程

    1,获取命令执行的结果,字符串拼接(脚本最常使用的功能)   cmd_result=$(date +%Y%b%d)        //使用变量获取命令执行的结果 或者 cmd_result=`date ...

  9. redis3.0 集群实战3 - java编程实战

    本文主要描述使用jedis进行redis-cluster操作   jedis jedis是redis官方推荐使用的java redis客户端,github地址为,https://github.com/ ...

  10. js事件绑定

    事件绑定,常见的是odiv.onclick=function(){..........};  这种方式绑定事件太单一,如果绑定多个,那么最后一个事件会覆盖掉之前的,也就是说只执行最后一次绑定的事件,这 ...