<题目链接>

题目大意:

  给你一个连通的无向图,问你删除每一条边后,是否能够出现一对(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】的更多相关文章

  1. hdu 5409 CRB and Graph(边双联通分量)

    题意: 给一个图一些边,保证图连通 问对于每条边,如果去除该边后使得图中一些点不连通.设这些点(u,v),要求使u尽量小,v尽量大,输出这样的(u,v).否则输出0 0. #include <b ...

  2. HDOJ 5409 CRB and Graph 无向图缩块

    无向图缩块后,以n所在的块为根节点,dp找每块中的最大值. 对于每一个桥的答案为两块中的较小的最大值和较小的最大值加1 CRB and Graph Time Limit: 8000/4000 MS ( ...

  3. 【HDU5409】CRB and Graph 边双联通 子树最值

    HDU # 题意 有一个简单图,n个点,m条边.对于每条割边,求出删去这条边后,在两个联通块中各取一个u,v.使得u<v,并且u尽量大而v尽量小. # 思路 求出边双联通是肯定的. 答案的限制条 ...

  4. HDU 4005 The war(边双连通)

    题意 ​ 给定一张 \(n\) 个点 \(m\) 条边的无向连通图,加入一条边,使得图中权值最小的桥权值最大,如果能使图中没有桥则输出 \(-1\). 思路 ​ 先对原图边双缩点,然后变成了一棵树.在 ...

  5. HDU 5416 CRB and Tree(前缀思想+DFS)

    CRB and Tree Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Tot ...

  6. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  7. 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 ...

  8. HDU 4005 The war(双连通好题)

    HDU 4005 The war pid=4005" target="_blank" style="">题目链接 题意:给一个连通的无向图.每条 ...

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

    首先双连通缩点建立新图(顺带求原图的总的桥数,事实上因为原图是一个强连通图,所以桥就等于缩点后的边) 此时得到的图类似树结构,对于新图求一次直径,也就是最长链. 我们新建的边就一定是连接这条最长链的首 ...

随机推荐

  1. oracle提高查询效率的34条方法

    注:本文来源:远方的守望者  <oracle提高查询效率的34条方法> oracle提高查询效率的34条方法 1.选择最有效率的表名顺序 (只在基于规则的优化器中有效): ORACLE的解 ...

  2. Confluence 6 MBeans

    你可以使用下面的 Confluence MBeans  来实时查看你 Confluence 实例运行的实时信息. CacheStatistics 这个 MBean 显示了 Confluence 有关的 ...

  3. netstat常见基本用法(转)

    netstat 简介 Netstat 是一款命令行工具,可用于列出系统上所有的网络套接字连接情况,包括 tcp, udp 以及 unix 套接字,另外它还能列出处于监听状态(即等待接入请求)的套接字. ...

  4. Android手机流量分析工具介绍

    一.20 Best Android Hacking Apps And Tools Of 2018 首先罗列常见的Android手机hacking的工具 #1The Android Network Ha ...

  5. Linux 编程笔记(三)

    上一章节对文件的基本属性做了一个笔记,续上次笔记对Linux文件的属性和属性组做一笔记 我安装的是虚拟机操作系统的版本还KaliLinux但是系统启动速度拖延,所以刚开始还是配置Centos 1.Li ...

  6. IP的计算

    IP的计算 时间限制: 1 Sec  内存限制: 32 MB 位无符号整数来表示,一般用点分方式来显示,点将IP地址分成4个部分,每个部分为8位,表示成一个无符号整数(因此不需要用正号出现),如192 ...

  7. Eclipse中java文件生成jar文件的方法

    在eclpse中找到你要导出的java程序 选中它   单击文件 -->export   在弹出的export对话框中找到 jar File 单击选中-->next   按图示顺序依次 选 ...

  8. 使用vue-cli 引入bootstrap.min.css文件报错

    可以在index.html 里面引入boostrap.min.css文件 将bootstrap.min.css文件放置于static/css/文件夹中 然后再index.html文件中引入便可 < ...

  9. AR 前言

    LBS 基于位置的服务,是指通过电信移动运营商的无线电通讯网络或外部定位方式,获取移动终端用户的位置信息,在GIS平台的支持下,为用户提供相应服务的一种增值业务. 它包括两层含义:首先是确定移动设备或 ...

  10. 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 ...