HDU 5409 CRB and Graph 【点双连通+DFS】
<题目链接>
题目大意:
给你一个连通的无向图,问你删除每一条边后,是否能够出现一对(u,v),使得u,v不连通,且u<v,如果有多对u,v,则输出尽量大的u,和尽量小的v。
解题分析:
首先要明确,因为该图是连通的无向图,所以删除的边是桥才能够使至少两点不连通。但是对于删除桥的情况,如何输出尽可能大的u和尽可能小的v呢?
我们要知道,删除一个桥,是将整张图分成两部分,这两部分的点仍然是连通的,并且,由于题目要求u<v,且u尽可能的大,v尽可能的小,所以,我们可以推断出,u与n一定不在同一部分,并且u是它所属部分的最大值,同时由于所有点的序号是连续的,u是那一部分的最大值,所以v的值一定是u+1。所以本题的目标就已经很明确了,就是先对每个点双连通分量进行缩点,并且维护每个连通分量的最大值。最后寻找u值得时候,就直接用DFS寻找不含n点的部分的最大值即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 1e5+;
#define clr(a,b) memset(a,b,sizeof(a))
struct Edge{
int to,next;
bool vis,bridge;
Edge(){}
Edge(int _to,int _next):to(_to),next(_next){vis=false;bridge=false;}
}e[MAXN<<];
int times,n,m,top,bcc,tot;
int dfn[MAXN],low[MAXN],pre[MAXN],head[MAXN],stk[MAXN],belong[MAXN],res[MAXN];
void init(){
top=times=bcc=tot=;
clr(head,-);clr(dfn,);clr(low,);clr(belong,);clr(pre,);
}
void addedge(int u,int v){
e[tot]=Edge(v,head[u]);head[u]=tot++;
e[tot]=Edge(u,head[v]);head[v]=tot++;
}
void Tarjan(int u){
dfn[u]=low[u]=++times;
stk[++top]=u;
for(int i=head[u];i!=-;i=e[i].next){
int v=e[i].to;
if(e[i].vis)continue;
e[i].vis=e[i^].vis=true; //将正反边全部标记
if(!dfn[v]){
pre[v]=u; //记录下父亲节点
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(!belong[v])low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
bcc++;
res[bcc]=-; //进行初始化
belong[u]=bcc;
while(true){
int v = stk[top--];
belong[v]=bcc;
res[bcc]=max(res[bcc],v); //维护连通分量中的最大值
if(v==u)break;
}
}
}
Edge edg[MAXN*];
int dep[MAXN],val[MAXN],head1[MAXN],tot1;
void init1(){
tot1=;
clr(head1,-);clr(dep,);
}
void AddEdge(int u,int v){
edg[tot1]=Edge(v,head1[u]);head1[u]=tot1++;
edg[tot1]=Edge(u,head1[v]);head1[v]=tot1++;
}
void dfs(int u,int d){ //得到以u为根的子树中编号最大的节点,并且得到每个节点的深度
dep[u]=d;
val[u]=res[u];
for(int i=head1[u];~i;i=edg[i].next){
int v=edg[i].to;
if(!dep[v]){
dfs(v,d+);
val[u]=max(val[u],val[v]); //val[u]为以u为根的子树中最大的编号
}
}
}
void solve(){
Tarjan();
for(int i=;i<tot;i++){ //遍历所有的边
if(e[i].bridge)continue;
int u=e[i].to,v=e[i^].to;
if(pre[v]==u&&dfn[u]<low[v]){ //如果u为v的父亲,且dfn[u]<low[v],说明u、v之间为桥
e[i].bridge=e[i^].bridge=true; //标记该边是否为桥
}
}
init1(); //为缩点后重新构图进行初始化
for(int i=;i<tot;i+=){
int u=e[i].to,v=e[i^].to;
if(belong[u]!=belong[v]){
AddEdge(belong[u],belong[v]); //缩点后进行重新构图
}
}
dfs(belong[n],); //以包含n的点双连通分量为树根
for(int i=;i<tot;i+=){
int u=e[i].to,v=e[i^].to;
if(e[i].bridge){ //因为肯定是两边中深度更浅的节点为根的子树中包含n节点,所以直接输出以深度更深的节点为根的最大值和这个最大值+1(这个最大值相当于是u,因为v>u,并且v要最小所以v为u+1)
if(dep[belong[u]]>dep[belong[v]])printf("%d %d\n",val[belong[u]],val[belong[u]]+);
else printf("%d %d\n",val[belong[v]],val[belong[v]]+);
}
else printf("0 0\n"); //如果不是桥,则输出0 0
}
}
int main(){
int T;scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
init();
for(int i=,x,y;i<m;i++){
scanf("%d%d",&x,&y);
addedge(x,y);
}
solve();
}
return ;
}
2018-12-04
HDU 5409 CRB and Graph 【点双连通+DFS】的更多相关文章
- hdu 5409 CRB and Graph(边双联通分量)
题意: 给一个图一些边,保证图连通 问对于每条边,如果去除该边后使得图中一些点不连通.设这些点(u,v),要求使u尽量小,v尽量大,输出这样的(u,v).否则输出0 0. #include <b ...
- HDOJ 5409 CRB and Graph 无向图缩块
无向图缩块后,以n所在的块为根节点,dp找每块中的最大值. 对于每一个桥的答案为两块中的较小的最大值和较小的最大值加1 CRB and Graph Time Limit: 8000/4000 MS ( ...
- 【HDU5409】CRB and Graph 边双联通 子树最值
HDU # 题意 有一个简单图,n个点,m条边.对于每条割边,求出删去这条边后,在两个联通块中各取一个u,v.使得u<v,并且u尽量大而v尽量小. # 思路 求出边双联通是肯定的. 答案的限制条 ...
- HDU 4005 The war(边双连通)
题意 给定一张 \(n\) 个点 \(m\) 条边的无向连通图,加入一条边,使得图中权值最小的桥权值最大,如果能使图中没有桥则输出 \(-1\). 思路 先对原图边双缩点,然后变成了一棵树.在 ...
- HDU 5416 CRB and Tree(前缀思想+DFS)
CRB and Tree Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Tot ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- HDU 3849 By Recognizing These Guys, We Find Social Networks Useful(双连通)
HDU 3849 By Recognizing These Guys, We Find Social Networks Useful pid=3849" target="_blan ...
- HDU 4005 The war(双连通好题)
HDU 4005 The war pid=4005" target="_blank" style="">题目链接 题意:给一个连通的无向图.每条 ...
- hdu 4612 Warm up 双连通缩点+树的直径
首先双连通缩点建立新图(顺带求原图的总的桥数,事实上因为原图是一个强连通图,所以桥就等于缩点后的边) 此时得到的图类似树结构,对于新图求一次直径,也就是最长链. 我们新建的边就一定是连接这条最长链的首 ...
随机推荐
- bat命令查询硬件信息
bat命令查询硬件信息 50 需求是这样的写一个bat命令,当命令执行的时候,先请用户输入姓名,然后继续执行查询出以下信息并写入一个文件,文件名称随便,文件可以放在与当前命令同一个文件夹下.最终文件中 ...
- Confluence 6 如何配置快速导航的同时查找数量
进入后台后查看快速导航的启用和可以同时查找的数量. 然后进行通过单击右上角的编辑(Edit)按钮进行编辑. 对配置进行配置,启用快速查询和可以同时使用的最大查询数量. https://www.cwik ...
- Confluence 6 管理你的 Confluence 许可证
你的许可证能够让你在运行 Confluence 的时候在指定的时间段获得特定的支持.同时这个许可证也定义了在你 Confluence 中可以使用的用户数量. 希望快速的查看当前的许可证信息,你可以进入 ...
- Confluence 6 布局高级自定义
重载 Velocity 模板 velocity 目录是 Confluence Velocity 模板文件进行搜索时候需要的文件夹.例如,你可以通过将你的 Velocity 文件使用正确的文件名放置到正 ...
- LeetCode(91):解码方法
Medium! 题目描述: 一条包含字母 A-Z 的消息通过以下方式进行了编码: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 给定一个只包含数字的非空字符串,请计 ...
- AI学习吧-REDIS-常识
Redis 是一个non-sql,非关系型数据库,数据存放在内存中,支持持久化,redis中的数据会在一段时间内和(mysql等数据库)磁盘进行同步,防止丢失,这样也就降低了读数据效率. Redis和 ...
- oracle 12c ORA-01017:invalid username/password; logon denied
Oracle 12C 中,想通过操作系统认证登录Oracle 数据库,有一些要注意的地方.不然就会遇到 ORA-01017:invalid username/password; logon denie ...
- 论文阅读笔记二十四:Rich feature hierarchies for accurate object detection and semantic segmentation Tech report(R-CNN CVPR2014)
论文源址:http://www.cs.berkeley.edu/~rbg/#girshick2014rcnn 摘要 在PASCAL VOC数据集上,最好的方法的思路是将低级信息与较高层次的上下文信息进 ...
- know yourself
Know yourself! ------Socrates 麦穗 古希腊有一位大学者,名叫苏格拉底.一天,他带领几个弟子来到一块麦地边.那正是收获的季节,地里满是沉甸甸的麦穗.苏格拉底对弟子们说:“你 ...
- 函数select、poll
函数select select函数: int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct ...