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 双连通缩点+树的直径
首先双连通缩点建立新图(顺带求原图的总的桥数,事实上因为原图是一个强连通图,所以桥就等于缩点后的边) 此时得到的图类似树结构,对于新图求一次直径,也就是最长链. 我们新建的边就一定是连接这条最长链的首 ...
随机推荐
- 机器学习之SVD分解
一.SVD奇异值分解的定义 假设是一个的矩阵,如果存在一个分解: 其中为的酉矩阵,为的半正定对角矩阵,为的共轭转置矩阵,且为的酉矩阵.这样的分解称为的奇异值分解,对角线上的元素称为奇异值,称为左奇异矩 ...
- PL\SQL 随学笔记
一.在PL\SQL语句块begin...end;中,不能直接使用select,必须与into结合查询. 例如: declare aa:=22; id2 integer; begin select * ...
- 第八单元 正文处理命令及tar命令
使用cat命令进行文件的纵向合并 两种文件的纵向合并方法 归档文件和归档技术 归档的目的 什么是归档 tar命令的功能 tar命令的常用选项 使用tar命令创建.查看及抽取归档文件 使用tar命令 ...
- cf1132G 线段树解分区间LIS(一种全新的线段树解LIS思路)+单调栈
/* 给定n个数的数列,要求枚举长为k的区间,求出每个区间的最长上升子序列长度 首先考虑给定n个数的数列的LIS求法:从左往右枚举第i点作为最大点的贡献, 那么往左找到第一个比a[i]大的数,设这个数 ...
- hdu2460 e-DCC染色缩点+暴力LCA
/* 给定一个无向图,往里面加边,问加第i条边时图中的桥数 首先肯定要求初始状态下的桥,染色缩点 每次给定的边为(u,v), 那么u->lca(u,v)->v路上的所有边都不再是桥 求LC ...
- Appium 九宫格 手势解锁
分析九宫格定位 整个九宫格是一个 view self.driver.find_element_by_id("com.elc:id/gesturepwd_create_lockview&q ...
- 微信小程序 Video默认横屏
wxml文件 <video id='myvideo' src='你的视频文件路径'> </video> js文件 onLoad: function (options) { va ...
- asp.net core WebApi 快速入门
参考:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/first-web-api?view=aspnetcore-2.1 官网的例子 直接 ...
- 【C#】wpf中的xmlns命名空间为什么是一个网址,代表了什么意思(转载)
原文:https://blog.csdn.net/catshitone/article/details/71213371 新建一个wpf的项目,我们先来看下它默认的命名空间都是哪些? 可以看到xmln ...
- java 使用jdbc连接Greenplum数据库和Postgresql数据库
1.公司使用的Greenplum和Postgresql,确实让我学到不少东西.简单将使用jdbc连接Greenplum和Postgresql数据库.由于使用maven仓库,不能下载Greenplum的 ...