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 双连通缩点+树的直径
首先双连通缩点建立新图(顺带求原图的总的桥数,事实上因为原图是一个强连通图,所以桥就等于缩点后的边) 此时得到的图类似树结构,对于新图求一次直径,也就是最长链. 我们新建的边就一定是连接这条最长链的首 ...
随机推荐
- oracle提高查询效率的34条方法
注:本文来源:远方的守望者 <oracle提高查询效率的34条方法> oracle提高查询效率的34条方法 1.选择最有效率的表名顺序 (只在基于规则的优化器中有效): ORACLE的解 ...
- Confluence 6 MBeans
你可以使用下面的 Confluence MBeans 来实时查看你 Confluence 实例运行的实时信息. CacheStatistics 这个 MBean 显示了 Confluence 有关的 ...
- netstat常见基本用法(转)
netstat 简介 Netstat 是一款命令行工具,可用于列出系统上所有的网络套接字连接情况,包括 tcp, udp 以及 unix 套接字,另外它还能列出处于监听状态(即等待接入请求)的套接字. ...
- Android手机流量分析工具介绍
一.20 Best Android Hacking Apps And Tools Of 2018 首先罗列常见的Android手机hacking的工具 #1The Android Network Ha ...
- Linux 编程笔记(三)
上一章节对文件的基本属性做了一个笔记,续上次笔记对Linux文件的属性和属性组做一笔记 我安装的是虚拟机操作系统的版本还KaliLinux但是系统启动速度拖延,所以刚开始还是配置Centos 1.Li ...
- IP的计算
IP的计算 时间限制: 1 Sec 内存限制: 32 MB 位无符号整数来表示,一般用点分方式来显示,点将IP地址分成4个部分,每个部分为8位,表示成一个无符号整数(因此不需要用正号出现),如192 ...
- Eclipse中java文件生成jar文件的方法
在eclpse中找到你要导出的java程序 选中它 单击文件 -->export 在弹出的export对话框中找到 jar File 单击选中-->next 按图示顺序依次 选 ...
- 使用vue-cli 引入bootstrap.min.css文件报错
可以在index.html 里面引入boostrap.min.css文件 将bootstrap.min.css文件放置于static/css/文件夹中 然后再index.html文件中引入便可 < ...
- AR 前言
LBS 基于位置的服务,是指通过电信移动运营商的无线电通讯网络或外部定位方式,获取移动终端用户的位置信息,在GIS平台的支持下,为用户提供相应服务的一种增值业务. 它包括两层含义:首先是确定移动设备或 ...
- HDU 1075 What Are You Talking About (stl之map映射)
What Are You Talking About Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 102400/204800 K ...