codeforces 962F.simple cycle(tarjan/点双连通分量)
题目连接:http://codeforces.com/contest/962/problem/F
题目大意是定义一个simple cycle为从一个节点开始绕环走一遍能经过simple cycle内任何一个节点,并且不超过一次。
因为是无向图,而且是环,即为连通分量,所以模型转化为求点双连通分量,依据题意求得的点双连通分量需要满足题目simple cycle的定义,所以当一个点双连通分量的边数量和点数量相等时才能构成simple cycle,在tarjan求割点的时候,需要存储点双联通分量的点和边的数量,最后判断一下是否相等,整体存储起来,最终排序一下满足题意的input边的目录。
AC代码:
#include<iostream>
#include<stack>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
using namespace std;
const int maxn = 1e5+7;
struct node{
vector<int> vex;
vector<int> num;
};//建图 vex为node[i]连接的节点,num储存node[i]和vex内节点连接边的序号
struct edge{
int a,b,id;
}E[maxn*2];//a为边的起点,b为边的终点,id为边的输入目录
stack<int> stk;//储存边的目录的栈
node g[100005];
int n,m,tot;
int BCC = 0;//统计BCC
int visit[200014],dfn[100005],low[100005],iscut[100005];
int bcc[100005];
vector<int> ans;
void tarjan(int x,int fa){
int child = 0;
low[x] = dfn[x] = ++tot;
for(int i = 0;i<g[x].vex.size() ;i++){
int tedge = g[x].num[i]; //边序号,后续可以由边序号作为索引找到该边的id(目录)
int temp = E[tedge].b;//temp为边的终点
if(temp == fa){
continue;
}
if(visit[tedge]){
continue;
}
visit[tedge] = visit[tedge^1] = 1;//标记双向边已经访问过
stk.push(tedge);
if(!dfn[temp]){
child++;
tarjan(temp,x);
low[x] = min(low[x],low[temp]);
if(low[temp]>=dfn[x])
{//找到割点,即找到一个点双连通分量
iscut[x] = 1;
BCC++;
set<int> Vset;//存该BCC的点
set<int> Eset;// 存该BCC的边
Vset.insert(x);
int s;
do{
s = stk.top();
stk.pop();
Eset.insert(E[s].id);//加入边的目录id
Vset.insert(E[s].b);//加入边的终点
}while(s!=tedge);
if(Eset.size() == Vset.size()){
for(set<int>::iterator it=Eset.begin();it!=Eset.end();it++)
ans.push_back(*it);//以题意要求判断是否为simple cycle
}
}
}
else
{
low[x] = min(low[x],dfn[temp]);
}
}
if(fa == -1 && child <2){
iscut[x] = 0;
}
}
int edgenum = 0;//边的序号从0开始,因为是建立双向边所以两条边标记的序号是异或关系,由边序号可以找到该边的id
void addedge(int u,int v,int id){
E[edgenum].a = u;
E[edgenum].b = v;
g[u].num.push_back(edgenum);
E[edgenum++].id = id;
}
int main(){
int n,m;
cin>>n>>m;
for(int i = 1;i<=m;i++){
int u,v;
cin>>u>>v;
addedge(u,v,i);
addedge(v,u,i);
g[u].vex.push_back(v);
g[v].vex.push_back(u);
}
for(int i = 1;i<=n;i++){
if(!dfn[i]){
tarjan(i,-1);
}
}
int cut = 0;
for(int i = 1;i<=n;i++){
if(iscut[i] == 1){
cut++;
}
}
sort(ans.begin(),ans.end());
cout<<ans.size()<<endl;
for(int i=0;i<(int)ans.size();i++)
cout<<ans[i]<<" ";
//cout<<BCC<<" "<<cut;
return 0;
}
codeforces 962F.simple cycle(tarjan/点双连通分量)的更多相关文章
- 【Codefoces487E/UOJ#30】Tourists Tarjan 点双连通分量 + 树链剖分
E. Tourists time limit per test: 2 seconds memory limit per test: 256 megabytes input: standard inpu ...
- Codeforces 521E - Cycling City(点双连通分量+分类讨论)
Codeforces 题面传送门 & 洛谷题面传送门 大家都是暴力找生成树然后跳路径,代码不到 50 行(暴论)的一说--好,那本蒟蒻决定提供一种代码 150 行,但复杂度也是线性的分类讨论做 ...
- CodeForces 97 E. Leaders(点双连通分量 + 倍增)
题意 给你一个有 \(n\) 个点 \(m\) 条边的无向图,有 \(q\) 次询问,每次询问两个点 \(u, v\) 之间是否存在长度为奇数的简单路径. \(1 \le n, m, q \le 10 ...
- [LA3523/uva10195]圆桌骑士 tarjan点双连通分量+奇环定理+二分图判定
1.一个环上的各点必定在同一个点双连通分量内: 2.如果一个点双连通分量是二分图,就不可能有奇环: 最基本的二分图中的一个环: #include<cstdio> #include<c ...
- POJ 3177 Redundant Paths (tarjan边双连通分量)
题目连接:http://poj.org/problem?id=3177 题目大意是给定一些牧场,牧场和牧场之间可能存在道路相连,要求从一个牧场到另一个牧场要有至少两条以上不同的路径,且路径的每条pat ...
- Codeforces962F Simple Cycles Edges 【双连通分量】【dfs树】
题目大意: 给出一个无向图,问有哪些边只属于一个简单环. 题目分析: 如果这道题我们掌握了点双连通分量,那么结论会很显然,找到每个点双,如果一个n个点的点双正好由n条边构成,那么这些边都是可以的. 这 ...
- 【BZOJ-1123】BLO Tarjan 点双连通分量
1123: [POI2008]BLO Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 970 Solved: 408[Submit][Status][ ...
- 图连通性【tarjan点双连通分量、边双联通分量】【无向图】
根据 李煜东大牛:图连通性若干拓展问题探讨 ppt学习. 有割点不一定有割边,有割边不一定有割点. 理解low[u]的定义很重要. 1.无向图求割点.点双联通分量: 如果对一条边(x,y),如果low ...
- tarjan 边双连通分量 对点进行分组 每组点都在一个双连通分量里边
int dfn[N],low[N],id[N],s[N],p,num,t,son[N];//dfn记录dfs时间戳//low代表当前点到达的最小时间戳,id对点进行分组编号.num是时间戳//s临时存 ...
随机推荐
- Oracle 12c 如何在 PDB 中添加 SCOTT 模式(数据泵方式)
Oracle 12c 建库后,没有 scott 模式,本篇使用数据泵方式,在12c版本之前数据库中 expdp 导出 scott 模式,并连接 12c 的 pdb 进行 impdp 导入. 目录 1. ...
- [Python]python已经安装了jieba库,Pycharm无法使用的问题
这个问题是Pycharm解释器的问题, 打开file--->setting---> 在如图所示界面点击add 在弹出的页面中选择python3的安装路径,可以用win10的搜索打开文件位置 ...
- 测试用例与PUCCH
- Educational Codeforces Round 76 (Rated for Div. 2)F - Make Them Similar
题意: 给你n个数字(<230),求出一个数字使得所有数字^这个数字之后,二进制状态下的1的个数相同. 解析: 因为最大数字二进制数有30位,所以分为前15位和后15位,分别枚举0-1<& ...
- layer弹出层右上角的关闭按钮怎么没有显示
问题描述:layer弹出层右上角的关闭按钮怎么没有显示,但鼠标移上去又可以点击 解决方式: 这是因为样式中需要一个图标,你的项目中缺少.解决如下:1.下载图标:http://www-x-zi-han- ...
- 主从分离之SSM与Mysql
大型网站为了软解大量的并发访问,除了在网站实现分布式负载均衡,远远不够.到了数据业务层.数据访问层,如果还是传统的数据结构,或者只是单单靠一台服务器扛,如此多的数据库连接操作,数据库必然会崩溃,数据丢 ...
- numpy 生成数组
可以看这个博客 https://www.cnblogs.com/td15980891505/p/6082858.html import numpy as np 建立数组并初始化数组 np.zeros( ...
- HTML页面学习
HTML 文档结构 <!DOCTYPE html> 文档声明 <html lang="en"> 语言 <head> 网站配置信息 <met ...
- ECMAScript基本语法——⑤运算符 一元运算符
++自增 在前先自增,再运算 在后先运算,再自增 --自减 在前先自减,再运算 在后先运算,再自减 +正号,-负号.表示数字的正负 注意:在JavaScript中,如果运算数不是运算符要求的类型, 那 ...
- 【Unity|C#】基础篇(4)——函数参数类型(值参/ref/out/params)
[学习资料] <C#图解教程>(第5章):https://www.cnblogs.com/moonache/p/7687551.html 电子书下载:https://pan.baidu.c ...