Proving Equivalences

题目链接(点击)

参考博客(点击)

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

Total Submission(s): 9497    Accepted Submission(s): 3349

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

思路:

题目搁了很久 昨天回头看题目的时候又看到了 想了好久没找到正确的方法 也没有思路 所以去看了看别人写的博客 虽然缩点和无环图变强连通图没有接触过 刚好学习了一下方法

缩点: 先通过tarjian算法把一个大的图分出来 好多强连通的小图 这样每个小图都有自己的编号(不会相同)

然后缩点就是将每个小图看成一个新的小点 然后重新将这些点连接起来 构成一个 有向无环图(DAG)

得到这个图之后通过判断 出、入度 就可以判断通添加几条边 可以让原来的大图变成前连通图

出、入度:将开始输入的每个边都重新遍历 (这就需要在输入的时候 要将两个点一起存 方便遍历)

例如输入:

1 2

1 3

如果这条边的两个点在不同的小图中:

将 1对应小图的编号 的 入度 +=2(因为输入的两次都是以1开始)

将2、3对应小图的编号的出度分别 +=1;

下面举个例子:其中共6个点 输入以下8条边

1 3

1 2

2 4

3 4

3 5

4 6

4 1

5 6

① 通过tarjian算法可以将一个大图分为三个强连通小图 分表标号 1、2、3 如下:

(如果编号最大才是1 那么就表示 不需要再添加边 该图已经是强连通图)

e

② 遍历输入的边可以发现;

3 5

4 6

5 6  这三条边满足小图编号不同

将3 4 5 对应的小图编号的入度+=1;

将5 6 6对应的小图编号的出度+=1;

③ 从1~3(编号最大为3) 遍历

分别判断入度和出度里面为0的个数

取个数最多的就是需要添加的边数使得该图变成强连通图

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int MAX=5e4;
int n,m;
int ans;
int head[MAX+5];
struct node{
int t;
int to;
int next;
}edge[MAX+5]; void addnode(int u,int v)
{
edge[ans].t=u;
edge[ans].to=v;
edge[ans].next=head[u];
head[u]=ans++;
} void allbegin()
{
memset(head,-1,sizeof(head));
ans=0;
}
int num,top,sig;
int dfn[MAX+5],sta[MAX+5],low[MAX+5],scc[MAX+5];
int inde[MAX+5],outde[MAX+5];
void dfs(int u)
{
dfn[u]=low[u]=++num;
sta[top++]=u;
for(int i=head[u];~i;i=edge[i].next){
int t=edge[i].to;
if(dfn[t]==0){
dfs(t);
low[u]=min(low[u],low[t]);
}
else if(scc[t]==0){
low[u]=min(low[u],low[t]);
}
}
if(dfn[u]==low[u]){
sig++;
while(1){
int j=sta[--top];
scc[j]=sig;
if(j==u){
break;
}
}
}
}
void tarjian()
{
sig=0,top=0,num=0;
memset(inde,0,sizeof(inde));
memset(outde,0,sizeof(outde));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(sta,0,sizeof(sta));
memset(scc,0,sizeof(scc));
for(int i=1;i<=n;i++){
if(dfn[i]==0){
dfs(i);
}
}
}
int main()
{
int T;
for(scanf("%d",&T);T--;){
allbegin();
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
int u,v;
scanf("%d%d",&u,&v);
addnode(u,v);
}
tarjian();
for(int i=0;i<m;i++){
int u=scc[edge[i].t];
int v=scc[edge[i].to];
if(u!=v){
inde[u]++;
outde[v]++;
}
}
int u=0,v=0;
for(int i=1;i<=sig;i++){
if(inde[i]==0){
u++;
}
if(outde[i]==0){
v++;
}
}
int maxx=max(u,v);
if(sig==1){ //如果编号最大才是1 那么就表示 不需要再添加边 该图已经是强连通图
printf("0\n");
}
else{
printf("%d\n",maxx);
}
}
return 0;
}

Proving Equivalences(缩点+有环图变强连通分量)【tarjian算法】的更多相关文章

  1. 图的强连通分量-Kosaraju算法

    输入一个有向图,计算每个节点所在强连通分量的编号,输出强连通分量的个数 #include<iostream> #include<cstring> #include<vec ...

  2. 求图的强连通分量--tarjan算法

    一:tarjan算法详解 ◦思想: ◦ ◦做一遍DFS,用dfn[i]表示编号为i的节点在DFS过程中的访问序号(也可以叫做开始时间)用low[i]表示i节点DFS过程中i的下方节点所能到达的开始时间 ...

  3. Kosaraju与Tarjan(图的强连通分量)

    Kosaraju 这个算法是用来求解图的强连通分量的,这个是图论的一些知识,前段时间没有学,这几天在补坑... 强连通分量: 有向图中,尽可能多的若干顶点组成的子图中,这些顶点都是相互可到达的,则这些 ...

  4. 寻找图的强连通分量:tarjan算法简单理解

    1.简介tarjan是一种使用深度优先遍历(DFS)来寻找有向图强连通分量的一种算法. 2.知识准备栈.有向图.强连通分量.DFS. 3.快速理解tarjan算法的运行机制提到DFS,能想到的是通过栈 ...

  5. Kosaraju算法解析: 求解图的强连通分量

    Kosaraju算法解析: 求解图的强连通分量 欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. 定义 连通分量:在无向图中,即为连 ...

  6. 图之强连通、强连通图、强连通分量 Tarjan算法

    原文地址:https://blog.csdn.net/qq_16234613/article/details/77431043 一.解释 在有向图G中,如果两个顶点间至少存在一条互相可达路径,称两个顶 ...

  7. 图的连通性:有向图强连通分量-Tarjan算法

    参考资料:http://blog.csdn.net/lezg_bkbj/article/details/11538359 上面的资料,把强连通讲的很好很清楚,值得学习. 在一个有向图G中,若两顶点间至 ...

  8. 萌新学习图的强连通(Tarjan算法)笔记

    --主要摘自北京大学暑期课<ACM/ICPC竞赛训练> 在有向图G中,如果任意两个不同顶点相互可达,则称该有向图是强连通的: 有向图G的极大强连通子图称为G的强连通分支: Tarjan算法 ...

  9. UVALIVE 4287 Proving Equivalences (强连通分量+缩点)

    题意:给定一个图,问至少加入多少条边能够使这个图强连通. 思路:首先求出这个图的强连通分量.然后把每个强连通分量缩成一个点.那么这个图变成了一个DAG,求出全部点的入度和出度,由于强连通图中每个节点的 ...

随机推荐

  1. 两圆相交求面积 hdu5120

    转载 两圆相交分如下集中情况:相离.相切.相交.包含. 设两圆圆心分别是O1和O2,半径分别是r1和r2,设d为两圆心距离.又因为两圆有大有小,我们设较小的圆是O1. 相离相切的面积为零,代码如下: ...

  2. Kattis - entertainmentbox

    题目链接:https://vjudge.net/problem/Kattis-entertainmentbox 题目大意: 一种叫做不知道什么的盒子可以同时录 k 个节目,现给出 n 个节目的开始和结 ...

  3. 一篇文教你使用python Turtle库画出“精美碎花小清新风格树”快来拿代码!

    Turtle库手册可以查询查询 python图形绘制库turtle中文开发文档及示例大全,手册中现有示例,不需要自己动手就可以查看演示. 使用Turtle画树,看了一下网上的代码,基本上核心的方法是使 ...

  4. JAVA 基础知识。程序运方法。

    dos     常用命令    dir     查看此文件夹目录下的所有程序    cd..    返回上一层目录    盘符:  直接切换至相应的盘符    cd 目录 切换至指定的目录    cd ...

  5. Life In Changsha College- 第三次冲刺

    第三次冲刺任务 设计登录注册功能. 用户故事 用户打开“生活在长大”的界面,选择登录 已注册过则输入用户名和密码直接登录 未注册用户则可选择注册功能,注册成功后登录 登录成功则弹出提示框 系统结构图环 ...

  6. [JavaWeb基础] 001.简单的JavaWeb代码和Tomcat配置部署

    简介: 其实说明白了就是J2EE应用开发,前端可以有很多的展现方式,后端由Java做逻辑运算和数据支撑.适用于创建服务器应用程序和服务,为搭建具有可伸缩性.灵活性.易维护性的商务系统提供了良好的机制. ...

  7. @Spring Boot程序员,我们一起给程序开个后门吧:让你在保留现场,服务不重启的情况下,执行我们的调试代码

    前言 这篇其实是对一年前的一篇文章的补坑. @Java Web 程序员,我们一起给程序开个后门吧:让你在保留现场,服务不重启的情况下,执行我们的调试代码 当时,就是在spring mvc应用里定义一个 ...

  8. 搭建SpringCloud微服务框架:一、结构和各个组件

    搭建微服务框架(结构和各个组件) 简介 SQuid是基于Spring,SpringBoot,使用了SpringCloud下的组件进行构建,目的是想搭建一套可以快速开发部署,并且很好上手的一套微服务框架 ...

  9. Jenkins漏洞利用复现

    一.未授权访问 访问url: http://172.16.20.134:8080/script 命令执行 println "ls -al".execute().text 也可以利用 ...

  10. Java-语言基础梳理

    1.java命名规范 包名:全小写 类名,接口名:首字母大写 变量名,方法名:第一个单词皆字母小写,后面单词首字母大写 常量名:所有字母都大写 2.变量 2.1 注意事项 作用域:一对{}之间有用 必 ...