Hdu 4612 Warm up (双连通分支+数的直径)

题目链接:

  Hdu 4612 Warm up

题目描述:

  给一个无向连通图,问加上一条边后,桥的数目最少会有几个?

解题思路:

  题目描述很清楚,题目也很裸,就是一眼看穿怎么做的,先求出来双连通分量,然后缩点重新建图,用bfs求树的直径,直径的长度就是减去桥的数目。

这个题目需要手动扩展,而且手动扩展的话要用C++提交,G++re哭了。

  1 #include <cstdio>
  2 #include <queue>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6 #pragma comment(linker, "/STACK:1024000000,1024000000")
  7 using namespace std;
  8
  9 const int maxn = 200005;
 10 struct node
 11 {
 12     int to, next;
 13 }edge[10*maxn], Edge[2*maxn];
 14 int vis[maxn], dist[maxn];
 15 int head[maxn], low[maxn], dfn[maxn], id[maxn], Head[maxn];
 16 int stack[maxn], tot, Tot, ntime, top, cnt, Max, end_p;
 17
 18 void init ()
 19 {
 20     tot = ntime = top = Tot = cnt = Max = end_p = 0;
 21     memset (id, 0, sizeof(id));
 22     memset (low, 0, sizeof(low));
 23     memset (dfn, 0, sizeof(dfn));
 24     memset (head, -1, sizeof(head));
 25     memset (stack, 0, sizeof(stack));
 26     memset (Head, -1, sizeof(Head));
 27 }
 28 void Add (int from, int to)
 29 {
 30     Edge[Tot].to = to;
 31     Edge[Tot].next = Head[from];
 32     Head[from] = Tot ++;
 33 }
 34 void add (int from, int to)
 35 {
 36     edge[tot].to = to;
 37     edge[tot].next = head[from];
 38     head[from] = tot ++;
 39 }
 40 void Tarjan (int u, int father)
 41 {
 42     int k = 0;
 43     low[u] = dfn[u] = ++ntime;
 44     stack[top++] = u;
 45     for (int i=head[u]; i!=-1; i=edge[i].next)
 46     {
 47         int v = edge[i].to;
 48         if (v == father && !k)
 49         {
 50             k ++;
 51             continue;
 52         }
 53         if (!dfn[v])
 54         {
 55             Tarjan (v, u);
 56             low[u] = min (low[u], low[v]);
 57         }
 58         else
 59             low[u] = min (low[u], dfn[v]);
 60     }
 61     if (low[u] == dfn[u])
 62     {
 63         cnt ++;
 64         while (1)
 65         {
 66             int v = stack[--top];
 67             id[v] = cnt;
 68             if (v == u)
 69                 break;
 70         }
 71     }
 72 }
 73 void bfs (int s)
 74 {
 75     queue<int>Q;
 76     int u, v;
 77     memset (vis, 0,sizeof(vis));
 78     vis[s] = 1;
 79     dist[s] = 0;
 80     Q.push(s);
 81     while (!Q.empty())
 82     {
 83         u = Q.front();
 84         Q.pop();
 85         for (int i=Head[u]; i!=-1; i=Edge[i].next)
 86         {
 87             v = Edge[i].to;
 88             if (!vis[v])
 89             {
 90                 vis[v] = 1;
 91                 dist[v] = dist[u] + 1;
 92                 Q.push(v);
 93                 if (dist[v] > Max)
 94                 {
 95                     Max = dist[v];
 96                     end_p = v;
 97                 }
 98             }
 99         }
100     }
101 }
102 void solve (int n)
103 {
104     int sum = 0;
105     Tarjan (1, 0);
106     for (int i=1; i<=n; i++)
107         for (int j=head[i]; j!=-1; j=edge[j].next)
108         {
109             int u = id[i];
110             int v = id[edge[j].to];
111             if (v != u)
112                 {
113                     Add (u, v);
114                     sum ++;
115                 }
116         }
117     sum /= 2;
118     bfs (1);
119     bfs (end_p);
120     printf ("%d\n", sum - Max);
121 }
122 int main ()
123 {
124     int n, m;
125     while (scanf ("%d %d", &n, &m), n+m)
126     {
127         init ();
128         while (m --)
129         {
130             int u, v;
131             scanf ("%d %d", &u, &v);
132             add (u, v);
133             add (v, u);
134         }
135         solve (n);
136     }
137     return 0;
138 }
时间: 2024-08-02 02:43:37

Hdu 4612 Warm up (双连通分支+数的直径)的相关文章

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

首先双连通缩点建立新图(顺带求原图的总的桥数,其实由于原图是一个强连通图,所以桥就等于缩点后的边) 此时得到的图类似树结构,对于新图求一次直径,也就是最长链. 我们新建的边就一定是连接这条最长链的首尾,这样就将原图的桥减少了直径个. #include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<algorithm> #include<map&g

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

Warm up Time Limit:5000MS     Memory Limit:65535KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4612 Description N planets are connected by M bidirectional channels that allow instant transportation. It's always possible to travel bet

hdu 4612 Warm up (带有重边的无向图Tarjan+树的直径)

Warm up Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 3947    Accepted Submission(s): 892 Problem Description N planets are connected by M bidirectional channels that allow instant transport

hdu 4612 缩点 桥 树的直径

// http://acm.hdu.edu.cn/showproblem.php?pid=4612 // 大致题意: 给n个点和m条边,组成一个无向连通图,问  给我加一条边的权力(可连接任意两点)->让图的桥数量最小,输出此时桥的数量.(2<=N<=200000, 1<=M<=1000000) // 无向环里面的边没有桥,缩点,因为是连通图,所以缩完点后构成了一棵树,每条树边都是一个桥.要加一条边使得加完后图的桥数最小,结合上述,所以选择连接树直径的两端点.ans = 原先

【HDU 4612 Warm up】BCC 树的直径

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4612 题意:一个包含n个节点m条边的无向连通图(无自环,可能有重边).求添加一条边后最少剩余的桥的数目. 思路:要想尽可能地消灭桥,那么添加的这条边一定是连通了最多的BCC. 所以首先进行双连通分量分解,并记录桥的数目:然后将同属一个BCC的点缩成一个,代之以block序号,以block序号为点将原图重构为一棵树. 最后求树的直径,桥的数目减去树的直径即为答案. 整体框架是学习了 http://w

HDU 4612 Warm up(边双联通求树的直径)

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

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

思路:强连通分量缩点,建立一颗新的树,然后求树的最长直径,然后加上一条边能够去掉的桥数,就是直径的长度. 树的直径长度的求法:两次bfs可以求,第一次随便找一个点u,然后进行bfs搜到的最后一个点v,一定是直径的一个端点(证明从略),第二次以点v为开头进行bfs,求出的最后一个点,就是直径的另一个端点,记录深度就是我们要求的长度.我这里是使用的bfs+dfs,是一样的,少开一个deep数组,节省一下空间吧…… 其实我一开始是不会求的,我以为随便一个叶子节点就可以做端点,交上去WA,当时还好奇感觉

F - Warm up - hdu 4612(缩点+求树的直径)

题意:有一个无向连通图,现在问添加一条边后最少还有几个桥 分析:先把图缩点,然后重构图为一棵树,求出来树的直径即可,不过注意会有重边,构树的时候注意一下 *********************************************************************** #pragma comment(linker, "/STACK:102400000,102400000")#include<stdio.h>#include<string.h

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

题意:一个无向图,问建立一条新边以后桥的最小数量. 分析:缩点以后,找出新图的树的直径,将这两点连接即可. 但是题目有个note:两点之间可能有重边!而用普通的vector保存边的话,用v!=fa的话是没办法让重边访问的,因此,使用数组模拟邻接表的方法来储存边. 这样,只要访问了一条边以后,令E[i].vis=E[i^1].vis=1即可,这样可以防止无向图的边和重边搞混.原理就是按位异或,一个奇数^1变为比它小1的偶数,反之亦然:如5^1=4,4^1=5. 具体见代码: 1 #include