Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4343    Accepted Submission(s): 1541

Problem Description
Consider the following exercise, found in a generic linear algebra textbook.

Let A be an n × n matrix. Prove that the following statements are equivalent:

1. A is invertible.
2. Ax = b has exactly one solution for every n × 1 matrix b.
3. Ax = b is consistent for every n × 1 matrix b.
4. Ax = 0 has only the trivial solution x = 0.

The typical way to solve such an exercise is to show a series of implications. For instance, one can proceed by showing that (a) implies (b), that (b) implies (c), that (c) implies (d), and finally that (d) implies (a). These four implications show that the four statements are equivalent.

Another way would be to show that (a) is equivalent to (b) (by proving that (a) implies (b) and that (b) implies (a)), that (b) is equivalent to (c), and that (c) is equivalent to (d). However, this way requires proving six implications, which is clearly a lot more work than just proving four implications!

I have been given some similar tasks, and have already started proving some implications. Now I wonder, how many more implications do I have to prove? Can you help me determine this?

 
Input
On the first line one positive number: the number of testcases, at most 100. After that per testcase:

* One line containing two integers n (1 ≤ n ≤ 20000) and m (0 ≤ m ≤ 50000): the number of statements and the number of implications that have already been proved.
* m lines with two integers s1 and s2 (1 ≤ s1, s2 ≤ n and s1 ≠ s2) each, indicating that it has been proved that statement s1 implies statement s2.

 
Output
Per testcase:

* One line with the minimum number of additional implications that need to be proved in order to prove that all statements are equivalent.

 
Sample Input
2
4 0
3 2
1 2
1 3
 
Sample Output
4
2
 
#include <bits/stdc++.h>
using namespace std;
const int N = 20005;
const int M = 50005; struct edge {
int v, next;
edge() {}
edge(int v, int next): v(v), next(next) {}
}e[M], e2[M]; int head[N], head2[N], num[N], in[N], out[N], tot, tot2;
int low[N], dfn[N], Stack[N], belong[N];
int scc, Index, top;
bool Instack[N]; void addedge(int u, int v, bool is) {
if(is) {
e[tot] = edge(v, head[u]);
head[u] = tot++;
}else {
e2[tot2] = edge(v, head2[u]);
head2[u] = tot2++;
}
} void Tarjan(int u) {
int v;
low[u] = dfn[u] = ++Index;
Stack[top++] = u;
Instack[u] = true;
for(int i = head[u]; ~i; i = e[i].next) {
v = e[i].v;
if(!dfn[v]) {
Tarjan(v);
if(low[u] > low[v]) low[u] = low[v];
}else if(Instack[v] && low[u] > dfn[v]) {
low[u] = dfn[v];
}
} if(low[u] == dfn[u])
{
scc++;
do {
v = Stack[--top];
Instack[v] = false;
belong[v] = scc;
num[scc]++;
} while(v != u);
}
} void solve(int n)
{
memset(dfn, 0, sizeof dfn);
memset(Instack, false, sizeof Instack);
memset(num, 0, sizeof num);
Index = scc = top = 0;
for(int i = 1; i <= n; ++i) if(!dfn[i]) Tarjan(i);
}
void init() {
tot = tot2 = 0;
memset(head, -1, sizeof head);
memset(head2, -1, sizeof head2);
} int main()
{
int _; scanf("%d", &_);
while(_ --)
{
init();
int n, m, u, v;
scanf("%d%d", &n, &m);
for(int i = 1; i <= m ;++i) {
scanf("%d%d", &u, &v);
addedge(u, v, true);
}
solve(n);
memset(in, 0, sizeof in);
memset(out, 0, sizeof out); for(int u = 1; u <= n; ++u) {
for(int i = head[u]; ~i; i = e[i].next) {
int v = e[i].v;
if(belong[u] != belong[v]) {
addedge(belong[u], belong[v], false);
}
}
}
for(int u = 1; u <= scc; ++u) {
for(int i = head2[u]; ~i; i = e2[i].next) {
int v = e2[i].v;
in[v]++;
out[u]++;
}
}
int a = 0, b = 0;
for(int i = 1; i <= scc; ++i) {
if(in[i] == 0) a++;
if(out[i] == 0) b++;
}
printf("%d\n", scc == 1 ? 0 : max(a, b));
}
return 0;
}

  

 
Source

hdu2767 Proving Equivalences Tarjan缩点的更多相关文章

  1. HDU2767 Proving Equivalences(加边变为强联通图)

    Proving Equivalences Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  2. HDU2767 Proving Equivalences

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission( ...

  3. UVALive 4287 Proving Equivalences(缩点)

    等价性问题,给出的样例为 a->b的形式,问要实现全部等价(即任意两个可以互相推出),至少要加多少个形如 a->b的条件. 容易想到用强连通缩点,把已经实现等价的子图缩掉,最后剩余DAG. ...

  4. hdu2767 Proving Equivalences --- 强连通

    给一个图,问至少加入�多少条有向边能够使图变成强连通的. 原图是有环的,缩点建图,在该DAG图上我们能够发现,要使该图变成强连通图必须连成环 而加入�最少的边连成环,就是把图上入度为0和出度为0的点连 ...

  5. hdu 2767 Proving Equivalences 强连通缩点

    给出n个命题,m个推导,问最少添加多少条推导,能够使全部命题都能等价(两两都能互推) 既给出有向图,最少加多少边,使得原图变成强连通. 首先强连通缩点,对于新图,每一个点都至少要有一条出去的边和一条进 ...

  6. UvaLive 4287 Proving Equivalences 强连通缩点

    原题链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...

  7. HDU2767Proving Equivalences tarjan缩点,如何求入度和出度最大值

    给定一个有向图,问最少增加多少条边后变成强连通图    tarjan求求强连通分量并缩点,如果强连通分量个数为1,则需要边数为0,  否则为缩点后点入度和出度的最大值,  证明:当入度或者出度不为0时 ...

  8. hdu2767 Proving Equivalences,有向图强联通,Kosaraju算法

    点击打开链接 有向图强联通,Kosaraju算法 缩点后分别入度和出度为0的点的个数 answer = max(a, b); scc_cnt = 1; answer = 0 #include<c ...

  9. HDU 2767 Proving Equivalences (Tarjan)

    Proving Equivalences Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other ...

随机推荐

  1. Linux 添加新硬盘 LVM操作(作用:新增硬盘的卷管理)

    1 查看当前系统硬盘及分区情况 (注:linux中SCSI的第1个硬盘/dev/sda,第2个硬盘/dev/sdb依此类推) 2 初始化分区sdb为物理卷pv pvcreate /dev/sdb  / ...

  2. .net在当前日期的基础上加一天

    比如今天是:2015-11-10 18:57:01,在这个基础上加一天,那么就是2015-11-11 18:57:01,代码如下: DateTime now_dt = DateTime.Now; ). ...

  3. 无法定位序数4369于动态链接库libeay32.dll

    c:\windows\system32目录下应该有libeay32.dll,可能它过于陈旧,需要换一个新版本的libeay32.dll

  4. [Android] Android5.1系统自带的应用启动次数统计

    reference to : http://blog.csdn.net/elder_sword/article/details/50508257 前段时间要做一个统计手机中激活量的东东,这个统计不是单 ...

  5. Android xml text 预览属性

    只在 AS 中生效 xmlns:tools="http://schemas.android.com/tools" tools:text="I am a title&quo ...

  6. java 中的一个项目如何做到访问另一个项目的一个方法 或者 页面

    两种方法:1.将一个项目打成jar包,第二个项目进行导入该jar包,就可以使用第一个项目里的类方法属性等2.将第一个项目发布出去,然后第二个项目调用,所谓发布出去就是开发远程接口,允许其他人调用.

  7. 从数据库导出数为生成excel表

    mysql -umaster -hxx.xx.xx.xx -p -e "set names utf8; use xxxdb;select * from t_order where t_ord ...

  8. JQuery阻止冒泡事件on绑定中异常情况分析

    科普下事件冒泡以及默认行为,以下面例子举列子:     事件冒泡:当点击内部button元素时,会触发自身及外层 a的点击事件,这就是事件冒泡引起的.事件会随着 DOM 的层次结构依次向上传播. 事件 ...

  9. 重温WCF之消息契约(MessageContract)(六)

    对于SOAP来说主要由两部分构成Header和Body,他们两个共同构成了SOAP的信封,通常来说Body保存具体的数据内容,Header保存一些上下文信息或关键信息.比如:在一些情况下,具有这样的要 ...

  10. Delphi多线程开发注意事项

    Q1: 多线程中需避免多个线程同时向全局变量进行写入操作,导致访问冲突问题. A1:  可以通过使用加锁机制(比如:临界区.互斥.信号量)解决此问题. Q2:多线程中对于结构体和CLASS类型的全局变 ...