Tarjan求缩点化强连通图
Describe:
求一个有向图加多少条边可以变成一个强连通图
Solution:
Tarjan缩点染色后,判断出度和入度,所有点的出度 = 0 的和 和 入度 = 0 的和的最大值即为所求。
缩点染色
for(int i = 1;i <= n;++i)
{
if(!dfn[i])
{
tarjan(i);
}
}
void tarjan(int s)
{
dfn[s] = low[s] = ++tot;
stk[stk_siz++] = s;
instk[s] = true; for(int i = id[s];~i;i = e[i].pre)
{
int to = e[i].to;
if(!dfn[to])
{
tarjan(to);
low[s] = min(low[s],low[to]);
}
else if(instk[to])
low[s] = min(low[s],dfn[to]);
}
if(dfn[s] == low[s])
{
++colid;
while(stk_siz > 0 && stk[stk_siz] != s)
{
--stk_siz;
int tmp = stk[stk_siz];
instk[tmp] = false;
col[tmp] = colid;
}
}
}
进行每一个缩点后的出度入度判断
for(int i = 0;i < m;++i)
{
from = e[i].from;
to = e[i].to;
//咋忘了缩点了!!这是缩点后的操作
// cout<<from<<" "<<to<<endl;
// cout<<col[from]<<" "<<col[to]<<endl;
if(col[from] != col[to])
{
in[col[to]]++;
out[col[from]]++;
}
}
int ret = 0,innum = 0,outnum = 0;
for(int i = 1;i <= colid;++i)
{
if(!in[i])innum++;
if(!out[i])outnum++;
}
ret = max(innum,outnum);
还要注意的就是缩成一个点的时候,也就是本来就是一个强连通分量是不需要添加边的
Coding:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 2e4 + 1e3;
const int maxm = 5e4 + 1e3;
struct node{
int from,to,pre;
node(){}
node(int to,int pre):to(to),pre(pre){}
}e[maxm];
int colid;
int id[maxn],cnt;
int col[maxn];
int in[maxn],out[maxn];
int dfn[maxn],low[maxn];
int tot;
int stk[maxn],stk_siz; bool instk[maxn];
void add(int from,int to)
{
e[cnt].to = to;
e[cnt].from = from;
e[cnt].pre = id[from];
id[from] = cnt++;
}
void init()
{
memset(id,-1,sizeof(id));
memset(instk,0,sizeof(instk));
memset(dfn,0,sizeof(dfn));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
cnt = tot = colid = stk_siz = 0;
}
void tarjan(int s)
{
dfn[s] = low[s] = ++tot;
stk[stk_siz++] = s;
instk[s] = true; for(int i = id[s];~i;i = e[i].pre)
{
int to = e[i].to;
if(!dfn[to])
{
tarjan(to);
low[s] = min(low[s],low[to]);
}
else if(instk[to])
low[s] = min(low[s],dfn[to]);
}
if(dfn[s] == low[s])
{
++colid;
while(stk_siz > 0 && stk[stk_siz] != s)
{
--stk_siz;
int tmp = stk[stk_siz];
instk[tmp] = false;
col[tmp] = colid;
}
}
}
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d%d",&n,&m);
int from,to;
for(int i = 1;i <= m;++i)
{
scanf("%d%d",&from,&to);
add(from,to);
}
for(int i = 1;i <= n;++i)
{
if(!dfn[i])
{
tarjan(i);
}
}
//边的存储是从1开始!!
for(int i = 0;i < m;++i)
{
from = e[i].from;
to = e[i].to;
//咋忘了缩点了!!这是缩点后的操作
// cout<<from<<" "<<to<<endl;
// cout<<col[from]<<" "<<col[to]<<endl;
if(col[from] != col[to])
{
in[col[to]]++;
out[col[from]]++;
}
}
int ret = 0,innum = 0,outnum = 0;
for(int i = 1;i <= colid;++i)
{
if(!in[i])innum++;
if(!out[i])outnum++;
}
ret = max(innum,outnum);
//特殊判断一下,一个点的时候(一种颜色的时候就是强连通了)
if(colid == 1)
printf("%d\n",0);
else
printf("%d\n",ret);
}
return 0;
}
Tarjan求缩点化强连通图的更多相关文章
- 【BZOJ3331】[BeiJing2013]压力 Tarjan求点双
[BZOJ3331][BeiJing2013]压力 Description 如今,路由器和交换机构建起了互联网的骨架.处在互联网的骨干位置的核心路由器典型的要处理100Gbit/s的网络流量.他们每天 ...
- tarjan求强连通分量+缩点+割点以及一些证明
“tarjan陪伴强联通分量 生成树完成后思路才闪光 欧拉跑过的七桥古塘 让你 心驰神往”----<膜你抄> 自从听完这首歌,我就对tarjan开始心驰神往了,不过由于之前水平不足,一 ...
- tarjan求强连通分量+缩点+割点/割桥(点双/边双)以及一些证明
“tarjan陪伴强联通分量 生成树完成后思路才闪光 欧拉跑过的七桥古塘 让你 心驰神往”----<膜你抄> 自从听完这首歌,我就对tarjan开始心驰神往了,不过由于之前水平不足,一 ...
- 连通分量模板:tarjan: 求割点 && 桥 && 缩点 && 强连通分量 && 双连通分量 && LCA(近期公共祖先)
PS:摘自一不知名的来自大神. 1.割点:若删掉某点后.原连通图分裂为多个子图.则称该点为割点. 2.割点集合:在一个无向连通图中,假设有一个顶点集合,删除这个顶点集合,以及这个集合中全部顶点相关联的 ...
- Tarjan求强连通分量,缩点,割点
Tarjan算法是由美国著名计算机专家发明的,其主要特点就是可以求强连通分量和缩点·割点. 而强联通分量便是在一个图中如果有一个子图,且这个子图中所有的点都可以相互到达,这个子图便是一个强连通分量,并 ...
- HDU 1827 Summer Holiday(tarjan求强连通分量+缩点构成新图+统计入度+一点贪心思)经典缩点入门题
Summer Holiday Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- Tarjan求强联通分量+缩点
提到Tarjan算法就不得不提一提Tarjan这位老人家 Robert Tarjan,计算机科学家,以LCA.强连通分量等算法闻名.他拥有丰富的商业工作经验,1985年开始任教于普林斯顿大学.Tarj ...
- POJ 1236 Network of Schools (tarjan算法+缩点)
思路:使用tarjan求强连通分量并进行缩点,判断所有入度为0的点,这个点就是必须要给予文件的点,分别计算出度,入度为零的点的个数,取二者的最大值就是把这个图变成强连通需要加的边数. 一个取值需要讨论 ...
- UESTC 901 方老师抢银行 --Tarjan求强连通分量
思路:如果出现了一个强连通分量,那么走到这个点时一定会在强连通分量里的点全部走一遍,这样才能更大.所以我们首先用Tarjan跑一遍求出所有强连通分量,然后将强连通分量缩成点(用到栈)然后就变成了一个D ...
随机推荐
- 转easyui datagrid 前台分页的实现
easyui datagrid 前台分页的实现java采用的版本 来源:本站原创 js知识 超过5,090人围观 暂无评论 使用easyui分页,有后台服务器端实现和前台浏览器端实现.服务器端实现按规 ...
- Eclipse中的maven项目搭建
一.eclipse中的maven设置 1.打开“首选项”----> "maven"---->"Installations".用来查看maven的使用 ...
- Python pip下载安装库 临时用清华镜像命令
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple C:\Users\mu\pip 新建pip.ini [global] index-url ...
- mybatis 操作数据错误Truncated incorrect DOUBLE value: ''
网上查到遇到次错误造成的原因: UPDATE TSYS_ROLE_RIGHTSET ACTIVE_FLAG = '2' and UPDATE_PERSON = 'CaiYiHua' and UPDA ...
- easyui下拉框过滤优化
项目中有个需求:编辑combobox的输入域会自动检索匹配项,当没有任何匹配项时,将combobox重置为初始状态. 处理方式:重写输入域的blur事件,判断当前值是否为加载的数据集的子集,如果不是则 ...
- 51nod1347 旋转字符串
题目很容易懂,只要进行几次简单的判断就能完成此题,显示判断是否为偶数,之后利用sustr截取两个字符串进行比较,代码如下 #include<iostream> #include<st ...
- 【Linux】开机自动启动脚本
Linux下(以RedHat为范本)添加开机开机自动启动脚本有两种方式; 本例系统:Linux(CentOS 7.2) 方法一 使用 /etc/rc.d/rc.local,自动启动脚本 #!/bin/ ...
- [C#]WinForm动态删除控件 Controls.Remove()
今天遇到一个奇怪的问题,在WinForm内动态添加Button后再动态的移除,发生稀奇古怪的现象,Button控件只被规律的移除,没有完全移除 foreach (Control c in this.C ...
- css的基础用法之标签选择
一.css的4种引入方式 #.内联式 <p style="color: red;font-size: 50px;text-align: center">Egon是一个非 ...
- oracle 分组中排序(rank函数)
需求: 查询每个供应商在每个类型产品销售的top50中有多少 分析: 1.查询,以指定字段(供应商.产品类型)分组,取每个分组的前50行,查看每个供应商的数量 2.使用rank函数给每个供应商.每个类 ...