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. Activity和Intent

  2. 洛谷4782 【模板】2-SAT 问题

    原题链接 \(2-SAT\)模板 #include<cstdio> using namespace std; const int N = 2e6 + 10; int fi[N], di[N ...

  3. BZOJ1233 干草堆 - 单调队列优化DP

    问题描述: 若有干个干草, 分别有各自的宽度, 要求将它们按顺序摆放, 并且每层的宽度不大于 它的下面一层 ,  求最多叠几层 题解: zkw神牛证明了: 底边最短, 层数最高         证明: ...

  4. 01. pt-align

    01. pt-align pt-align xxx.txt =========================================== pt-align对齐输出格式 name city a ...

  5. ES6 中 let and const

    let 和 const 命令 let 命令 基本用法 ES6 新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效. { let a = 10; v ...

  6. ubuntu下安装配置ADB

    1.下载SDK Tools for Linux,地址:http://developer.android.com/sdk/index.html 2.解压,将 android-sdk-linux 文件夹放 ...

  7. MS-Office使用技巧

    1.角标设置 下角标:选中(Shift+左右方向键)-->Ctrl+= 上角标:选中(Shift+左右方向键)-->Ctrl+Shift+=(Ctrl++) 撤销:同样操作 2.MS Of ...

  8. ES开发的一些坑(一)

    一.ES-Hadoop导数据的时候报"Could not write all entries"异常  ES-Hadoop是一个开源的数据导入项目,支持数据从hdfs,hive,sp ...

  9. vue 获取跳转上一页组件信息

    项目中有一需求,需要根据不同的页面路径url跳转进行不同的操作,首先需要获得上一页面的url,利用 beforeRouteEnter 这个钩子中的from参数获得之前url的信息,然后给 next 传 ...

  10. 对象回收过程?线程池执行过程? map原理?集合类关系?synchronized 和 volatile ? 同一个类的方法事务传播控制还有作用吗?java 锁

    1.  对象回收过程? 可达性分析算法: 如果一个对象从 GC Roots 不可达时,则证明此对象不可用. 通过一系列称为GC ROOTS的对象作为起点,从这些起点往下搜索,搜索走过的路径 称为引用链 ...