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 ...
随机推荐
- hdu 1026(BFS+输出路径) 我要和怪兽决斗
http://acm.hdu.edu.cn/showproblem.php?pid=1026 模拟一个人走迷宫,起点在(0,0)位置,遇到怪兽要和他决斗,决斗时间为那个格子的数字,就是走一个格子花费时 ...
- IntelliJ idea 的破解
·1.破解的jar包下载链接: https://pan.baidu.com/s/1JV6GwguGQNs5pNQtst29Hw 提取码: u2jd 2.安装和破解地址:https://www.cnb ...
- HTTP.ContentType
1. multipart/x-mixed-replace http://blog.dubbelboer.com/2012/01/08/x-mixed-replace.html
- BZOJ1935或洛谷2163 [SHOI2007]园丁的烦恼
BZOJ原题链接 洛谷原题链接 很容易想到二维前缀和. 设\(S[i][j]\)表示矩阵\((0, 0)(i, j)\)内树木的棵数,则询问的矩形为\((x, y)(xx, yy)\)时,答案为\(S ...
- openssl_error_string()
其实已经成功了,openssl_error_string()一样会输出错误信息,忽略就好
- 解决mysql安装出现error Nr.1045问题
我们在windows下安装mysql最后一步时会出现Access denied for user 'root'@localhost'(using password:No)的问题.这几个问题经常出现在卸 ...
- SQL 将一个表中的所有记录插入到一个临时表中
insert into #tempTable select * from TempTable WHERE + 查询条件
- having 的用法
聚合函数 where 后面不能直接使用聚合函数 处理函数 题目 编写一个 SQL 查询,查找 Person 表中所有重复的电子邮箱. 示例: +----+---------+ | Id | Email ...
- h5常用标签语义
<article>定义页面独立的内容区域.例如外部来的文章. <aside>定义页面的侧边栏内容.<aside> 标签定义 <article> 标签外的 ...
- 811. Subdomain Visit Count
这题主要难在构建关联容器,方法很多,但是核心都是把原字符串一截一截减下来处理,先把前面用空格隔开的次数转化为整数,然后处理后面的多层子域. 方法一,查找标志字符,用标志字符把字符串分成几段 stati ...