给我们一个有向图,有两个问题

1、最少要给多少个点发消息,才能使得所有的点都收到消息(消息可以随边传递)

2、最少需要多少条边才能使得图变成强连通图

对于一个强连通分量,可以当做一个点来考虑,所以我们可以缩点,然后得到DAG图,

那么对于第一个问,即是入度为0的点有多少个,因为入度为0的点无法收到消息。

对于第二问,只要加max(s1,s2)条边,就能使得DAG变成强连通图,  s1表示入度为0的点的个数,s2表示出度为0的点的个数

设s1 > s2, 那么首先加s2条边,这s2条边连接的是入度为0和出度为0的点,

然后剩下s1-s2个入度为0的点, 那么随便加s1-s2条边即可。

 #pragma warning(disable:4996)
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <bitset>
#include <algorithm>
#include <iostream>
#include <string>
#include <functional>
#include <iostream>
typedef __int64 LL;
const int INF = << ;
using namespace std;
/*
考虑如果是的一个有向图,变成连通图,
将强联通分量缩成一个点,
然后,如果某一个联通分量和其他的联通分量没有边,那么要加两条边,如果只有一条边
那么只要加1条边
*/
const int N = + ;
int dfn[N], low[N], sccno[N], dfs_clock, cnt;
stack<int> st;
vector<int> g[N]; void tarjan(int u, int fa)
{
dfn[u] = low[u] = ++dfs_clock;
st.push(u);
for (int i = ; i<g[u].size(); ++i)
{
int v = g[u][i];
if (dfn[v] == )
{
tarjan(v, u);
low[u] = min(low[u], low[v]);
}
else if (sccno[v] == )//因为有向图存在横插边,不能用横插边来更新low[u]
{
low[u] = min(low[u], low[v]);
}
}
//同样,因为强连通分量可以分布在根结点的两个分支上,所以在递归返回的时候调用
if (low[u] == dfn[u])
{
cnt++;
for (;;)
{
int x = st.top();
st.pop();
sccno[x] = cnt;
if (x == u)
break;
}
}
}
bool in[N], out[N];
int main()
{ int n;
while (scanf("%d", &n) != EOF)
{
dfs_clock = cnt = ;
while (!st.empty()) st.pop();
for (int i = ;i <= n;++i)
{
sccno[i] = ;
g[i].clear();
low[i] = dfn[i] = ;
in[i] = out[i] = false;
}
for (int i = ;i <= n;++i)
{
int u = i, v;
while (scanf("%d", &v), v)
g[u].push_back(v);
}
for (int i = ;i <= n;++i)
{
if (dfn[i] == )
tarjan(i, -);
}
for (int i = ;i <= n;++i)
{
for (int j = ;j < g[i].size();++j)
{
int v = g[i][j];
if (sccno[i] == sccno[v]) continue;
out[sccno[i]] = true;
in[sccno[v]] = true;
}
}
if (cnt == )
{
printf("1\n0\n");
continue;
}
int cnt1 = , cnt2 = ;
for (int i = ;i <= cnt;++i)
{
if (!in[i]) cnt1++;
if (!out[i]) cnt2++;
}
printf("%d\n", cnt1);
printf("%d\n", max(cnt1, cnt2));
}
return ;
}

poj1236 有向图加边变成强连通图的更多相关文章

  1. hdu1269迷宫城堡(判断有向图是否是一个强连通图)

    1 /* 题意: 给你一个图,求这个有向图示否是一个强连通图(每两个节点都是可以相互到达的)! 思路1:按正向边dfs一遍,将经过的节点计数,如果记录的节点的个数小于n,那么就说明图按照正向边就不是连 ...

  2. 有向图 加最少的边 成为强连通分量的证明 poj 1236 hdu 2767

    poj 1236: 题目大意:给出一个有向图, 任务一: 求最少的点,使得从这些点出发可以遍历整张图  任务二: 求最少加多少边 使整个图变成一个强连通分量. 首先任务一很好做, 只要缩点 之后 求 ...

  3. POJ 1236——Network of Schools——————【加边形成强连通图】

    Network of Schools Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u ...

  4. Tarjan求缩点化强连通图

    Describe: 求一个有向图加多少条边可以变成一个强连通图 Solution: Tarjan缩点染色后,判断出度和入度,所有点的出度 = 0 的和 和 入度 = 0 的和的最大值即为所求. 缩点染 ...

  5. tarjan有向图的强连通

    强连通:在有向图G中,两个顶点间至少存在一条路径,则两个点强连通. 强连通图:在有向图中,每两个顶点都强连通,则有向图G就是一个强连通图. 强连通分量:在非强连通图中的极大强连通子图,就称为强连通分量 ...

  6. [Tarjan系列] Tarjan算法与有向图的SCC

    前面的文章介绍了如何用Tarjan算法计算无向图中的e-DCC和v-DCC以及如何缩点. 本篇文章资料参考:李煜东<算法竞赛进阶指南> 这一篇我们讲如何用Tarjan算法求有向图的SCC( ...

  7. 清华集训2015-Day 1

    玛里苟斯 一个大小为 \(n\) 的可重集合 \(a\) ,求 \(\mathbb E[x^k]\) ,其中 \(x\) 为 \(a\) 的一个子集的异或和. \(n\le 10^5,1\le k\l ...

  8. LOJ 一本通一句话题解系列:

    第一部分 基础算法 第 1 章 贪心算法 1):「一本通 1.1 例 1」活动安排:按照结束时间排序,然后扫一遍就可以了. 2):「一本通 1.1 例 2」种树:首先要尽量的往区间重叠的部分种树,先按 ...

  9. dfs判断连通图(无向)

    在图论中,连通图基于连通的概念.在一个无向图 G 中,若从顶点vi到顶点vj有路径相连(当然从vj到vi也一定有路径),则称vi和vj是连通的.如果 G 是有向图,那么连接vi和vj的路径中所有的边都 ...

随机推荐

  1. HUNNU11342:Chemistry(模拟)

    http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11342 Problem description The ch ...

  2. read table 时关键字TRANSPORTING NO FIELDS的用法

    关键字TRANSPORTING NO FIELDS 用于read table with key 一般用于等读取内表的时候,只是判断该内表中是否有次数据 不需要读取到工作区中. READ TABLE g ...

  3. 排序(6)---------归并排序(C语言实现)

    归并排序: 归并操作,也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作.归并排序算法依赖归并操作. 归并操作的步骤例如以下:     (1) 申请空间,使其大小为两个已经排序序列之和.该空 ...

  4. Android Studio中如何打JAR包

    Android Studio中对于library类型的Moudle,默认打出来的是AAR包, 但有时候我们的SDK还需要共享给一些其他eclipse的项目使用,这样我们就需要输出JAR包, 可以通过在 ...

  5. Java实现敏感词过滤(转)

    敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来 ...

  6. [c++语法]类

    什么是类 类 是 面向对象的基础.c里面是没有对象的,只有数据,即静态的死物. 从面向过程升级到面向对象后,有了对象的概念,对象是数据与方法的合体,是动态的活物. 类代表着一类事物的特征.而对象,是类 ...

  7. 拆分字符串,GetHtmlByWebBrowser,UnicodeToMBCS,提升进程权限

    1. // 根据字符串,拆分字符串,相当于vb中的split函数 function SplitString(const Source, ch: string): TStringList; var te ...

  8. 移植ffmpeg到VC环境心得

    所有想学习ffmpeg的网友有福了,大名鼎鼎的ffmpeg,移植到Windows的VC6版本全部开源,编译环境为VC6+SP5+VCPP5.别忘记了顶贴哦. 移植ffmpeg到windows,主要的修 ...

  9. 区间Dp 暴力枚举+动态规划 Hdu1081

    F - 最大子矩形 Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I64u Submit Status Des ...

  10. Android中的跨进程通信方法实例及特点分析(二):ContentProvider

    1.ContentProvider简单介绍 在Android中有些数据(如通讯录.音频.视频文件等)是要供非常多应用程序使用的.为了更好地对外提供数据.Android系统给我们提供了Content P ...