Warm up---hdu4612(缩点,树的直径)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612
给一个无向图, 加上一条边后,求桥最少有几个;
那我们加的那条边的两个顶点u,v;一定是u,v之间含有桥的数量最多,然后uv之间的桥都没了,剩下的就是要求的结果;
树的直径的定义刚好就是两个节点之间含有最多的边;
下面是有关树的直径的知识;


这个题目需要手动扩展,不然会爆栈,而且手动扩展的话要用C++提交。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
#define N 200005
int Head1[N], Head2[N], cnt[];
int Stack[N], top, dfn[N], low[N], Time, n, m;
int nBridge, Bridge[N];
int dist[N], vis[N], Max, index, Is[N];
struct Edge
{
int v, next;
} e1[*N], e2[*N];
void Init()
{
top = nBridge = Time = Max = index = ;
cnt[] = cnt[] = ;
memset(low, , sizeof(low));
memset(dfn, , sizeof(dfn));
memset(Bridge, , sizeof(Bridge));
memset(dist, , sizeof(dist));
memset(Stack, , sizeof(Stack));
memset(Is, , sizeof(Is));
memset(Head1, -, sizeof(Head1));
memset(Head2, -, sizeof(Head2));
}
void Add(Edge e[],int Head[], int u, int v, int k)
{
e[cnt[k]].v = v;
e[cnt[k]].next = Head[u];
Head[u] = cnt[k]++;
}
void Tarjar(int u, int father)
{
low[u] = dfn[u] = ++Time;
Stack[top++] = u;
Is[u] = ;
int v, k=;
for(int i=Head1[u]; i!=-; i=e1[i].next)
{
v = e1[i].v;
if(v==father && !k)///避免重边;
{
k++;
continue;
}
if(!dfn[v])
{
Tarjar(v, u);
low[u] = min(low[u], low[v]);
}
else
low[u] = min(low[u], dfn[v]);
}
if(low[u] == dfn[u])
{
nBridge++;///可以代表缩点后的节点个数;
while()
{
v = Stack[--top];
Is[v] = ;
Bridge[v] = nBridge;///缩点;
if(u==v) break;
}
}
}
void bfs(int s)
{
queue<int>Q;
int p, q;
memset(vis, , sizeof(vis));
vis[s] = ;
dist[s] = ;
Q.push(s);
while(!Q.empty())
{
p = Q.front(); Q.pop();
for(int i=Head2[p]; i!=-; i=e2[i].next)
{
q = e2[i].v;
if(!vis[q])
{
vis[q] = ;
dist[q] = dist[p] + ;
Q.push(q);
if(Max<dist[q])
{
Max = dist[q];
index = q;
}
}
}
}
}
int main()
{
int u, v;
while(scanf("%d%d", &n, &m), m + n)///输入时由于m n弄反了,TLE的我想哭;
{
Init();
for(int i=; i<=m; i++)
{
scanf("%d%d", &u, &v);
Add(e1, Head1, u, v, );
Add(e1, Head1, v, u, );///原来的树;
}
Tarjar(, );
for(int i=; i<=n; i++)
{
for(int j=Head1[i]; j!=-; j=e1[j].next)
{
int u = Bridge[i];
int v = Bridge[e1[j].v];
if(u != v )
{
Add(e2, Head2, u, v, );
Add(e2, Head2, v, u, );///缩点后的树;
}
}
}
bfs();
bfs(index);///求树的直径的过程;
printf("%d\n", nBridge--Max);///缩点后形成的树每条边都是桥;所以总桥的个数为节点数-1;
}
return ;
}
一年后又来写了一下,比不用扩栈也可以;
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<string>
#include<stack>
#include<map>
using namespace std;
#define N 205010
#define INF 0x3f3f3f3f
#define met(a, b) memset(a, b, sizeof(a)) vector<vector<int> >G;
vector<vector<int> >G1;
int low[N], dfn[N], Time;
int Block[N], nblock;
int IsStack[N], Sta[N], top;
int n, m, nbridge; void Init()
{
met(low, );
met(dfn, );
met(Block, );
met(IsStack, );
met(Sta, );
G.clear();
G.resize(n+);
G1.clear();
G1.resize(n+);
Time = nblock = top = nbridge = ;
} void Tarjan(int u, int fa)
{
low[u] = dfn[u] = ++Time;
IsStack[u] = ;
Sta[top++] = u;
int len = G[u].size(), v, k = ;
for(int i=; i<len; i++)
{
v = G[u][i];
if(v == fa && !k)
{
k++;
continue;
}
if(!dfn[v])
{
Tarjan(v, u);
low[u] = min(low[u], low[v]); if(low[v] > dfn[u])
nbridge ++;
}
else if(IsStack[v])
{
low[u] = min(low[u], dfn[v]);
}
}
if(low[u] == dfn[u])
{
++nblock;
do
{
v = Sta[--top];
IsStack[v] = ;
Block[v] = nblock;
}while(u != v);
}
} int vis[N], Max, Index, dist[N]; void bfs(int s)
{
met(vis, );
met(dist, );
vis[s] = ;
queue<int> Q;
Q.push(s);
while(Q.size())
{
int p = Q.front();Q.pop();
int len = G1[p].size(), q;
for(int i=; i<len; i++)
{
q = G1[p][i];
if(!vis[q] && dist[q] < dist[p]+)
{
dist[q] = dist[p]+;
if(dist[q] > Max)
{
Max = dist[q];
Index = q;
}
vis[q] = ;
Q.push(q);
}
}
}
} int main()
{
while(scanf("%d %d", &n, &m), m+n)
{
Init(); int u, v;
for(int i=; i<=m; i++)
{
scanf("%d %d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
Tarjan(, );
for(int i=; i<=n; i++)
{
int len = G[i].size(), v, u = Block[i];
for(int j=; j<len; j++)
{
v = Block[G[i][j]];
if(u != v)
{
G1[u].push_back(v);
G1[v].push_back(u);
}
}
}
Max = , Index = -;
bfs();
bfs(Index);
///printf("%d %d\n", nbridge, Max);
printf("%d\n", nbridge-Max);///或者nblock-1-Max;
}
return ;
}
Warm up---hdu4612(缩点,树的直径)的更多相关文章
- HDU4612:Warm up(缩点+树的直径)
Warm up Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Su ...
- HDU4612 Warm up 边双(重边)缩点+树的直径
题意:一个连通无向图,问你增加一条边后,让原图桥边最少 分析:先边双缩点,因为连通,所以消环变树,每一个树边都是桥,现在让你增加一条边,让桥变少(即形成环) 所以我们选择一条树上最长的路径,连接两端, ...
- hdu4612 Warm up 缩点+树的直径
题意抽象后为:给定一个无向图 问添加一条边的情况下最少能有多少个桥. 桥的定义:删除该边后原图变为多个连通块. 数据规模:点数N(2<=N<=200000),边数M(1<=M< ...
- hdu 4612 Warm up 有重边缩点+树的直径
题目链接 Warm up Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Tot ...
- hdu4612(双连通缩点+树的直径)
传送门:Warm up 题意:询问如何加一条边,使得剩下的桥的数目最少,输出数目. 分析:tarjan缩点后,重新建图得到一棵树,树上所有边都为桥,那么找出树的直径两个端点连上,必定减少的桥数量最多, ...
- hdu-4612(无向图缩点+树的直径)
题意:给你n个点和m条边的无向图,问你如果多加一条边的话,那么这个图最少的桥是什么 解题思路:无向图缩点和树的直径,用并查集缩点: #include<iostream> #include& ...
- HDU 4612 Warm up (边双连通分量+缩点+树的直径)
<题目链接> 题目大意:给出一个连通图,问你在这个连通图上加一条边,使该连通图的桥的数量最小,输出最少的桥的数量. 解题分析: 首先,通过Tarjan缩点,将该图缩成一颗树,树上的每个节点 ...
- F - Warm up HDU - 4612 tarjan缩点 + 树的直径 + 对tajan的再次理解
题目链接:https://vjudge.net/contest/67418#problem/F 题目大意:给你一个图,让你加一条边,使得原图中的桥尽可能的小.(谢谢梁学长的帮忙) 我对重边,tarja ...
- 4612 warm up tarjan+bfs求树的直径(重边的强连通通分量)忘了写了,今天总结想起来了。
问加一条边,最少可以剩下几个桥. 先双连通分量缩点,形成一颗树,然后求树的直径,就是减少的桥. 本题要处理重边的情况. 如果本来就两条重边,不能算是桥. 还会爆栈,只能C++交,手动加栈了 别人都是用 ...
- codeforces GYM 100114 J. Computer Network 无相图缩点+树的直径
题目链接: http://codeforces.com/gym/100114 Description The computer network of “Plunder & Flee Inc.” ...
随机推荐
- perl 中的哈希赋值
在perl 中,通过代码动态的给哈希赋值,是最常见的应用场景,但是有些情况下,我们事先知道一些信息,当需要把这些信息存放进一个哈希的时候,直接给哈希赋值就好: 哈希的key不用说,就是一个字符串,关键 ...
- php中获取网站访客来源的关键词方法
php中获取网站访客来源的关键词方法,收集了 <?php class keyword{ public function getKeyword($referer){ if(strpos($refe ...
- Windows "计划任务"功能设置闹钟~
相信很多人和我一样在使用电脑时都会遇到这样一个麻烦:不知道如何在windows 中设置一个闹铃.当我们在“开始”菜单的所有程序中找了一遍又一遍,甚至使用Everything.exe做全盘的搜索,都没有 ...
- mysql数据库中,查看当前支持的字符集有哪些?字符集默认的collation的名字?
需求描述: mysql数据库支持很多字符集,那么如何查看当前的mysql版本中支持的或者说可用的字符集有什么呢? 操作过程: 1.使用show character set的方式获取当前版本中支持的字符 ...
- 从头认识java-16.5 nio的数据转换
这一章节我们来讨论一些nio的数据转换. 上面一章节我们提到ByteBuffer,可是他是面向二进制数据,对于编程来说不是非常方便,因此,java添加了转换数据的工具. 1.asCharBuffer ...
- csu1510 Happy Robot 递推
题目链接: cid=2095&pid=7">csu1510 解题思路: 要求解四个值x_min,x_max,y_min,y_max 首先考虑x_min怎样得到:由于机器人最后有 ...
- Extjs 自定义控件
// JavaScript Document Ext.namespace('CRM.Panels'); CRM.Panels.UserDetail = Ext.extend(Ext.Panel,{ w ...
- ios开发之--使用toolbar调整item之间的间隔
toolbar的item有很多种样式,其实经常使用的就几种, UIBarButtonSystemItemFixedSpace 木棍:可以理解为固定的长度 UIBarButtonSystemItemFl ...
- iOS根据文字字数动态确定Label宽高
我们有时候在写项目的时候,会碰到,意见反馈,还有其他地方,讲座活动细则等需要大篇展示的文本, 因为每次服务器返回的内容大小不一,所以需要动态的调整label的宽高: 在ios 6 的时候可以: -(v ...
- nagios监控mysql
在nagios上部署check_mysql_health 监控mysql 博客分类: 架构 本监控为基于nagios服务器主动监控方法,利用check_mysql_health实现多种监控模式: ...