UVA796 Critical Links(求桥) 题解
题意:求桥
思路:求桥的条件是:(u,v)是父子边时 low[v]>dfn[u]
所以我们要解决的问题是怎么判断u,v是父子边(也叫树枝边)。我们在进行dfs的时候,要加入一个fa表示当前进行搜索的点的父节点。v=edge[v].v,如果dfn[v]==0即没访问过,那么肯定是父子边;如果v已经被访问过,我们就要做出筛选,只有v!=fa才进行low[u]=min(low[u],dfn[v]),因为v==fa时,(u,v)变成了返祖边,这时候low[u]被刷新成为fa的dfn,但是low是通过父子边所能找到的最早节点,固要舍去这种情况。
code:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<queue>
#include<cmath>
#include<string>
#include<map>
#include<stack>
#include<set>
#include<vector>
#include<iostream>
#include<algorithm>
#include<sstream>
#define ll long long
const int N=1e5+5;
const ll INF=1e5+5;
using namespace std;
int n,m,cnt,ecnt,num;
int dfn[N],low[N],head[N];
vector<int> g[N];
struct Edge{
int u,v,next;
}edge[N*10];
struct Ans{
int u,v;
}ans[N*10];
int cmp(Ans a,Ans b){
if(a.u<b.u) return 1;
else if(a.u==b.u && a.v<b.v) return 1;
return 0;
}
void add(int u,int v){
edge[num].u=u;
edge[num].v=v;
edge[num].next=head[u]; //表头
head[u]=num++;
}
void tarjan(int x,int fa){ //fa是x的父节点
dfn[x]=low[x]=++cnt;
for(int i=head[x];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(!dfn[v]){
tarjan(v,x);
low[x]=min(low[x],low[v]);
if(low[v]>dfn[x]){
int a,b;
a=x,b=v;
if(a>b) swap(a,b);
ans[ecnt].u=a,ans[ecnt].v=b;
ecnt++;
}
}
else if(v!=fa){
low[x]=min(low[x],dfn[v]);
}
}
}
void init(){
cnt=ecnt=num=0;
memset(head,-1,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
}
int main(){
int t,T,a,b,n;
while(~scanf("%d",&t)){
init();
T=t;
while(T--){
scanf("%d (%d)",&a,&n);
while(n--){
scanf("%d",&b);
add(a,b);
}
}
for(int i=0;i<t;i++){
if(!dfn[i]) tarjan(i,i);
}
sort(ans,ans+ecnt,cmp);
cout<<ecnt<<" critical links"<<endl;
for(int i=0;i<ecnt;i++){
printf("%d - %d\n",ans[i].u,ans[i].v);
}
cout<<endl;
}
return 0;
}
这是在加边的时候判断是否重边
code2:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<queue>
#include<cmath>
#include<string>
#include<map>
#include<stack>
#include<set>
#include<vector>
#include<iostream>
#include<algorithm>
#include<sstream>
#define ll long long
const int N=1e5+5;
const ll INF=1e5+5;
using namespace std;
int n,m,cnt,ecnt,num;
int dfn[N],low[N],head[N];
vector<int> g[N];
struct Edge{
int u,v,next;
int flag;
}edge[N*10];
struct Ans{
int u,v;
}ans[N*10];
int cmp(Ans a,Ans b){
if(a.u<b.u) return 1;
else if(a.u==b.u && a.v<b.v) return 1;
return 0;
}
void add(int u,int v){
for(int i=head[u];i!=-1;i=edge[i].next){
if(edge[i].v==v){ //说明不是桥
edge[i].flag++;
edge[num].u=u;
edge[num].v=v;
edge[num].flag=1;
edge[num].next=head[u]; //表头
head[u]=num++;
return;
}
}
edge[num].u=u;
edge[num].v=v;
edge[num].flag=0;
edge[num].next=head[u]; //表头
head[u]=num++;
}
void tarjan(int x,int fa){ //fa是x的父节点
dfn[x]=low[x]=++cnt;
for(int i=head[x];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==fa) continue;
if(!dfn[v]){
tarjan(v,x);
low[x]=min(low[x],low[v]);
if(low[v]>dfn[x] && edge[i].flag==0){
int a,b;
a=x,b=v;
if(a>b) swap(a,b);
ans[ecnt].u=a,ans[ecnt].v=b;
ecnt++;
}
}
else{
low[x]=min(low[x],dfn[v]);
}
}
}
void init(){
cnt=ecnt=num=0;
memset(head,-1,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
}
int main(){
int t,T,a,b,n;
while(~scanf("%d",&t)){
init();
T=t;
while(T--){
scanf("%d (%d)",&a,&n);
while(n--){
scanf("%d",&b);
add(a,b); //这里不能加add(b,a),在读到b时会加这条边,否则在下一次add(b,a)会判重边
}
}
for(int i=0;i<t;i++){
if(!dfn[i]) tarjan(i,i);
}
sort(ans,ans+ecnt,cmp);
cout<<ecnt<<" critical links"<<endl;
for(int i=0;i<ecnt;i++){
printf("%d - %d\n",ans[i].u,ans[i].v);
}
cout<<endl;
}
return 0;
}
UVA796 Critical Links(求桥) 题解的更多相关文章
- [UVA796]Critical Links(割边, 桥)
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...
- UVA796 - Critical Links(Tarjan求桥)
In a computer network a link L, which interconnects two servers, is considered critical if there are ...
- UVA796 Critical Links —— 割边(桥)
题目链接:https://vjudge.net/problem/UVA-796 In a computer network a link L, which interconnects two serv ...
- uva-796.critical links(连通图的桥)
本题大意:求出一个无向图的桥的个数并且按照顺序输出所有桥. 本题思路:注意判重就行了,就是一个桥的裸题. 判重思路目前知道的有两种,第一种是哈希判重,第二种和邻接矩阵的优化一样,就是只存图的上半角或者 ...
- Uva 796 Critical Links 找桥
这个题很简单,但是输入有毒,用字符串的我一直RE 然后换成这样瞬间AC #include <stdio.h> #include <string.h> #include < ...
- Uva796 Critical Links
用tarjan缩点 然后用dfn[u] < low[v]缩点并且保存起来 在sort一遍输出 #include<stdio.h> #include<string.h> # ...
- UVA796:Critical Links(输出桥)
Critical Links 题目链接:https://vjudge.net/problem/UVA-796 Description: In a computer network a link L, ...
- uva 796 C - Critical Links(tarjan求桥)
题目链接:https://vjudge.net/contest/67418#problem/C 题意:求出桥的个数并且按顺序输出 题解:所谓桥就是去掉这条边后连通块增加,套用一下模版就行. #incl ...
- UVA 796 Critical Links(Tarjan求桥)
题目是PDF就没截图了 这题似乎没有重边,若有重边的话这两点任意一条边都不是桥,跟求割点类似的原理 代码: #include <stdio.h> #include <bits/std ...
随机推荐
- dedecms如何调用当前栏目的子栏目及子栏目文章
前面ytkah谈到了 dedecms调用当前栏目的子栏目怎么操作,有的朋友会问如果再增加一个调用子栏目文章的需求,即调用当前栏目的子栏目及子栏目文章,这个有办法实现吗?这时就要涉及到另外两个标签的调用 ...
- CentOS7.1.x+Druid 0.12 集群配置
原文转载自:https://blog.csdn.net/bigtree_3721/article/details/79583008 先决条件:安装版本列表 本次安装满足下面的条件: CentOS v7 ...
- CentOS6.5安装Redis数据库
1.以安装redis2.8.19为例 下载安装包:http://redis.io tar zxvf redis-2.8.19.tar.gz #解压 cd redis-2.8.19 #进入解压后的文件夹 ...
- nltk模块基础操作
几个基础函数 (1)搜索文本:text.concordance(word) 例如,在text1中搜索词”is”在文本中出现的次数以及上下文的词:text1.concordance("is& ...
- VirtualBox 虚拟磁盘的UUID修改
个人测试环境,想构建一套Standby RAC环境,不想再重复去安装系统浪费时间,直接复制之前安装RAC前的一套VirtualBox的虚拟环境,不过打开时报错: 未能打开位于 Z:\Vbox\Stan ...
- LeetCode7.反转整数
给定一个 32 位有符号整数,将整数中的数字进行反转. 示例 1: 输入: 123 输出: 321 示例 2: 输入: -123 输出: -321 示例 3: 输入: 120 输出: 21 注意: 假 ...
- 利用lodop打印控件轻松实现批量打印 (转载http://www.thinkphp.cn/topic/13085.html)
最近在做一个打印程序,要实现批量打印功能,在网上找了很多天,也在tp官网咨询大牛们,对大家的的提议我一一进行了研究,总结如下: 要实现批量打印可以有两个办法: 一是利用专业的报表程序,能实现十分复杂的 ...
- WPF学习笔记-用Expression Design制作矢量图然后导出为XAML
WPF学习笔记-用Expression Design制作矢量图然后导出为XAML 第一次用Windows live writer写东西,感觉不错,哈哈~~ 1.在白纸上完全凭感觉,想象来画图难度很大, ...
- [转]Visual C++ RunTime的特征——非烫即屯
Visual C++ RunTime的特征——非烫即屯 大一刚学C语言,第二次上机课,当我发现我照着书抄写的程序在运行之外的黑框里面跳出一排“烫烫烫烫烫”,当时就震惊了.你们能想象一个来自小城, 在大 ...
- Java Nested Classes(内部类~第一篇英文技术文档翻译)
鄙人最近尝试着翻译了自己的第一篇英文技术文档.Java Nested Classes Reference From Oracle Documentation 目录 嵌套类-Nested Classes ...