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 ...
随机推荐
- PAT 1061 判断题(15)(代码)
1061 判断题(15 分) 判断题的评判很简单,本题就要求你写个简单的程序帮助老师判题并统计学生们判断题的得分. 输入格式: 输入在第一行给出两个不超过 100 的正整数 N 和 M,分别是学生人数 ...
- andorid 练习微信登陆
AndroidManifest.xml layout1.xml <?xml version="1.0" encoding="utf-8"?> < ...
- android xml 解析汉字只出来一个字的问题
DocumentBuilderFactory factory = DocumentBuilderFactory .newInstance(); // 实例化DocumentBuilder factor ...
- Spring 是如何解析泛型 - ResolvalbeType
Spring 是如何解析泛型 - ResolvalbeType Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Java ...
- 【UI测试】--安全性
- 【NIFI】 实现数据库到数据库之间数据同步
本里需要基础知识:[NIFI] Apache NiFI 安装及简单的使用 数据同步 界面如下: 具体流程: 1.使用ExecuteSQL连接mysql数据库,通过写sql查询所需要的数据 2.nifi ...
- JNI,RegisterNative参数解析
Register native method - 数据类型和method descriptor 使用JNI时,为了使得虚拟机可以找到在C/C++ code中定义的native方法,有两种机制可以用,一 ...
- kbmmw 的HTTPSmartService 上传文件到服务器端
前面我写过了 HTTPSmartService 使用介绍,可以参见以前的文章. 前一向有同学问如何在http 页面表单上上传文件.一直没有时间回答,自己简单做了例子, 发现无法实现功能,今天花了一天时 ...
- 创建视图&新建表按照视图结构
create view V_tableTemp as select a.* from TEMPCLIENT a ,TEMPCLIENTSTUFF b where a.CORNO<>' ...
- 检索 COM 类工厂中 CLSID 为 {10021F00-E260-11CF-AE68-00AA004A34D5} 的组件失败,原因是出现以下错误: 80040154 没有注册类 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG))。
ASP.NET利用SQLDMO可以实现在线备份.还原数据库等各种功能. 由于客户的数据库和WEB服务不再同一台服务器,把网站部署在服务器上以后,运行程序,提示如下错误 当使用Interop.SQLDM ...