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求缩点化强连通图的更多相关文章

  1. 【BZOJ3331】[BeiJing2013]压力 Tarjan求点双

    [BZOJ3331][BeiJing2013]压力 Description 如今,路由器和交换机构建起了互联网的骨架.处在互联网的骨干位置的核心路由器典型的要处理100Gbit/s的网络流量.他们每天 ...

  2. tarjan求强连通分量+缩点+割点以及一些证明

    “tarjan陪伴强联通分量 生成树完成后思路才闪光 欧拉跑过的七桥古塘 让你 心驰神往”----<膜你抄>   自从听完这首歌,我就对tarjan开始心驰神往了,不过由于之前水平不足,一 ...

  3. tarjan求强连通分量+缩点+割点/割桥(点双/边双)以及一些证明

    “tarjan陪伴强联通分量 生成树完成后思路才闪光 欧拉跑过的七桥古塘 让你 心驰神往”----<膜你抄>   自从听完这首歌,我就对tarjan开始心驰神往了,不过由于之前水平不足,一 ...

  4. 连通分量模板:tarjan: 求割点 &amp;&amp; 桥 &amp;&amp; 缩点 &amp;&amp; 强连通分量 &amp;&amp; 双连通分量 &amp;&amp; LCA(近期公共祖先)

    PS:摘自一不知名的来自大神. 1.割点:若删掉某点后.原连通图分裂为多个子图.则称该点为割点. 2.割点集合:在一个无向连通图中,假设有一个顶点集合,删除这个顶点集合,以及这个集合中全部顶点相关联的 ...

  5. Tarjan求强连通分量,缩点,割点

    Tarjan算法是由美国著名计算机专家发明的,其主要特点就是可以求强连通分量和缩点·割点. 而强联通分量便是在一个图中如果有一个子图,且这个子图中所有的点都可以相互到达,这个子图便是一个强连通分量,并 ...

  6. HDU 1827 Summer Holiday(tarjan求强连通分量+缩点构成新图+统计入度+一点贪心思)经典缩点入门题

    Summer Holiday Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  7. Tarjan求强联通分量+缩点

    提到Tarjan算法就不得不提一提Tarjan这位老人家 Robert Tarjan,计算机科学家,以LCA.强连通分量等算法闻名.他拥有丰富的商业工作经验,1985年开始任教于普林斯顿大学.Tarj ...

  8. POJ 1236 Network of Schools (tarjan算法+缩点)

    思路:使用tarjan求强连通分量并进行缩点,判断所有入度为0的点,这个点就是必须要给予文件的点,分别计算出度,入度为零的点的个数,取二者的最大值就是把这个图变成强连通需要加的边数. 一个取值需要讨论 ...

  9. UESTC 901 方老师抢银行 --Tarjan求强连通分量

    思路:如果出现了一个强连通分量,那么走到这个点时一定会在强连通分量里的点全部走一遍,这样才能更大.所以我们首先用Tarjan跑一遍求出所有强连通分量,然后将强连通分量缩成点(用到栈)然后就变成了一个D ...

随机推荐

  1. css font-size=0的妙用

    转自:css font-size=0有什么妙用? 回答一: 问题的根源是 inline(a标签默认是display:inline) 和 inline-block (.list-info 设置的是 di ...

  2. PAT 1051 复数乘法(15 )(代码+思路)

    1051 复数乘法(15 分) 复数可以写成 (A+Bi) 的常规形式,其中 A 是实部,B 是虚部,i 是虚数单位,满足 i​2​​=−1:也可以写成极坐标下的指数形式 (R×e​(Pi)​​),其 ...

  3. UI和View 三种控制方式

    AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xm ...

  4. CF402D Upgrading Array

    原题链接 先用素数筛筛下素数,然后考虑贪心去操作. 先求前缀\(GCD\)(求到\(GCD\)为\(1\)就不用再往下求了),得到数组\(G[i]\),然后从后往前扫,如果\(f(G[i]) < ...

  5. 说说为什么会有ssl.CertificateError报错

    有一些网站没有获取浏览器的颁发的安全证书 当你在请求这个网站时浏览器会当做不安全网站处理 因此会报ssl.CertificateError 解决办法是 :将默认的证书验证模式修改为不需要验证 代码如下 ...

  6. 简单的node 服务端 响应get,返回json数据;

    原文:http://blog.csdn.net/xn_28/article/details/50837019 const http = require('http'); const hostname ...

  7. BZOJ 3329 - Xorequ - 数位DP, 矩乘

    Solution 发现 $x \ xor \  2x = 3x$ 仅当 $x$ 的二进制中没有相邻的 $1$ 对于第一个问题就可以进行数位DP 了. 但是对于第二个问题, 我们只能通过递推 打表 来算 ...

  8. BIO,NIO,AIO(NIO2)的理解

    写在前面,这里所说的IO主要是强调的网络IO 1.BIO(同步并阻塞) 客户端一个请求对应一个线程.客户端上来一个请求(最开始的连接以及后续的IO请求),服务端新建一个线程去处理这个请求,由于线程总数 ...

  9. sqlserver 数据分发复制 发布订阅

    转载地址:https://www.cnblogs.com/lizejia/p/6062674.html

  10. sql条件查询-日期比较(取年月部分)

    查询当年当月的数据: select * from compalete_task where to_Char(create_date,'yyyyMM') = to_Char(sysdate,'yyyyM ...