Proving Equivalences UVALive 4287 图的强连通分量

Consider the following exercise, found in a generic linear algebra textb o ok.

LetAbe ann×nmatrix. Prove that the following statements are equivalent:
(a) Ais invertible.
(b) Ax=bhas exactly one solution for everyn×1 matrixb.
(c) Ax=bis consistent for everyn×1 matrixb.
(d) Ax= 0 has only the trivial solutionx= 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 nally 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 rst line one positive number: the number of testcases, at most 100. After that per testcase:
One line containing two integers n (1 n 20000) andm(0m50000): the number of
statements and the number of implications that have already been proved.
m lines with two integerss1ands2(1s1, s2nands1̸=s2) each, indicating that it has been
proved that statement s 1 implies statement s 2.
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
42

题目大意:每个问题对应一个结点,两个问题已经有implications 表示两个结点之间有了一条边;把所有的问题看成一个图,要证明各个问题等价,就是要使整个图成为一个强连通分量。需要求解最少还需要几条边?

解题思路:求出题中的强连通分量,然后将每个强连通分量看成一个“点”;然后统计每个“点”的ID和OD,如果某个“点”的ID=0,则idcnt+1,如果某个点的OD=0,则odcnt+1,最后max(idcnt,odcnt)就是结果。(不理解ID,OD,连通分量这些名词的同学,请参考《算法导论》这本书)

算法知识:经典的强连通分量入门题目,tarjan算法+缩点 或者 kosaraju算法+缩点

学习说明:求解强连通分量常用的算法有tarjan算法、kosaraju算法。kosaraju算法我是在《算法导论》书上学的,tarjan算法是在网上学的,给出我看的几个链接:

http://blog.sina.com.cn/s/blog_69a101130100k1cm.html

https://www.byvoid.com/blog/scc-tarjan/

http://baike.baidu.com/link?url=pFZBstBZdR5ERYMExvpdHAHqBlt2RK0ZbESX_53Ui456lBW6eR7hZSlJ1AseVnrFlVzGC2ANGAuVKlW04r7ukq

Tarjan算法的伪代码如下:

tarjan(u)
{
    DFN[u]=Low[u]=++Index                      // 为节点u设定次序编号和Low初值
    Stack.push(u)                              // 将节点u压入栈中
    for each (u, v) in E                       // 枚举每一条边
        if (v is not visted)               // 如果节点v未被访问过
            tarjan(v)                  // 继续向下找
            Low[u] = min(Low[u], Low[v])
        else if (v in S)                   // 如果节点v还在栈内
            Low[u] = min(Low[u], DFN[v])
    if (DFN[u] == Low[u])                      // 如果节点u是强连通分量的根
        repeat
            v = S.pop                  // 将v退栈,为该强连通分量中一个顶点
            print v
        until (u== v)
}

参考源代码:

tarjan算法:http://blog.csdn.net/hcbbt/article/details/38301669

kosaraju算法:http://blog.csdn.net/lenleaves/article/details/8982673

我写的源代码:

///对图可以使用结构体存储,也可以使用vector存储,采用的邻接链表的思路
///这里使用vector,方便我熟悉
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#define N 20010
#define WHITE 0
#define GRAY 1
#define BLACK 2
using namespace std;
vector<int> vec[N];///存储每一条边,vec数组的下标是结点的编号
stack<int> node;

int n=0,m=0,t=0;
int scc[N];///存储每个结点所属的强连通分量,数组下标是结点编号,数组的值是结点所属的强连通分量的值
int color[N];///存储每个结点的颜色,白色表示没有访问,灰色表示还在stack中,黑色表示已经生成了强连通分量
int low[N];///每个结点的low值
int dfn[N];///每个结点的dfn值
int sccid[N];///存储每个强连通分量的入度
int sccod[N];///存储每个SCC的出度
int ans=0;///最后的结果
int lowcnt=0,dfncnt=0;
int scccnt=0;///强连通分量的编号,从0开始

int tarjan(int i){///i是结点编号
    int temp=0;
    node.push(i);
    color[i]=GRAY;
    lowcnt++;dfncnt++;
    low[i]=lowcnt;dfn[i]=dfncnt;///从1开始编号
    for(unsigned int j=0;j<vec[i].size();j++){
        if(color[vec[i][j]]==WHITE){
            tarjan(vec[i][j]);
            low[i]=min(low[i],low[vec[i][j]]);
        }
        else if(color[vec[i][j]]==GRAY){
            low[i]=min(low[i],dfn[vec[i][j]]);
        }
    }
    if(low[i]==dfn[i]){///产生一个SCC(强连通分量)
        do{
            temp=node.top();
            scc[temp]=scccnt;///存储该节点对应的SCC
            node.pop();
            color[temp]=BLACK;///出栈后为black,表示已经为该节点分配SCC
        }while(temp!=i);
        scccnt++;///SCC的编号值+1
    }
    return 0;
}
int cmscc(){
    for(int i=1;i<=n;i++){
        if(color[i]==WHITE){
            tarjan(i);
        }
    }
    return 0;
}
int findiod(){
    int idcnt=0,odcnt=0;
    for(int i=1;i<=n;i++){
        for(unsigned int j=0;j<vec[i].size();j++){
            if(scc[i]!=scc[vec[i][j]]){///如果两个相邻结点不属于一个SCC
                sccod[scc[i]]++;///i结点的SCC出度加1
                sccid[scc[vec[i][j]]]++;///j结点的scc入度加1
            }
        }
    }
    if(scccnt>1)///scccnt=1的时候,只有一个连通分量,输出必然是0;
    for(int i=0;i<scccnt;i++){
        if(sccid[i]==0) idcnt++;
        if(sccod[i]==0) odcnt++;
    }
    ans=max(idcnt,odcnt);
    return 0;
}
int read(){
    int nod1=0,nod2=0;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        vec[i].clear();
    }
    for(int i=1;i<=m;i++){
        cin>>nod1>>nod2;
        vec[nod1].push_back(nod2);///0下标的vector不使用
    }
    return 0;
}
int main()
{

    cin>>t;
    while(t--)
    {
        memset(scc,0,sizeof(scc));
        memset(color,0,sizeof(color));
        memset(low,0,sizeof(low));
        memset(dfn,0,sizeof(dfn));
        memset(sccid,0,sizeof(sccid));
        memset(sccod,0,sizeof(sccod));
        ans=0;lowcnt=0;dfncnt=0;scccnt=0;
        read();
        cmscc();///计算强连通分量
        findiod();///计算出度入度
        cout<<ans<<endl;
    }
    return 0;
}


 













1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值