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:
- A is invertible.
- Ax = b has exactly one solution for every n × 1 matrix b.
- Ax = b is consistent for every n × 1 matrix b.
- 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?
2 4 0 3 2 1 2 1 3
4 2
#include<map> #include<cmath> #include<stack> #include<queue> #include<ctime> #include<cctype> #include<string> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; const int maxn = 20000 + 5; const int maxv = 50000 + 5; int T,n,m,s1,s2; int dfn[maxn]; //深度优先访问次序 int low[maxn]; //能追溯到的最早次序 vector<int>G[maxn]; //存图 stack<int>sta; //存储已遍历的点 bool InStack[maxn]; //是否在栈中 int index1; //索引号 int index2; //强连通分量个数 int sccno[maxn]; //缩点 int indegree[maxn]; //入度 int outdegree[maxn]; //出度 void init(){ memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(sccno,0,sizeof(sccno)); memset(InStack,false,sizeof(InStack)); memset(indegree,0,sizeof(indegree)); memset(outdegree,0,sizeof(outdegree)); while(!sta.empty()) sta.pop(); for(int i=1;i<=n;i++) G[i].clear(); index1=0; index2=0; } void input(){ scanf("%d%d",&n,&m); for(int i=0;i<m;i++){ scanf("%d%d",&s1,&s2); G[s1].push_back(s2); } } void tarjan(int u){ dfn[u]=low[u]=++index1; sta.push(u); InStack[u]=true; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); } if(InStack[v]){ low[u]=min(low[u],dfn[v]); } } if(low[u]==dfn[u]){ index2++; while(!sta.empty()){ int j=sta.top(); sta.pop(); InStack[j]=false; sccno[j]=index2; if(j==u) break; } } } void findscc(){ for(int i=1;i<=n;i++){ if(!dfn[i]) tarjan(i); } } int work(){ findscc(); if(index2==1) return 0; for(int u=1;u<=n;u++){ for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(sccno[u]!=sccno[v]){ int uu=sccno[u]; int vv=sccno[v]; outdegree[uu]++; indegree[vv]++; } } } int in=0,out=0; for(int i=1;i<=index2;i++){ if(indegree[i]==0) in++; if(outdegree[i]==0) out++; } return max(in,out); } void solve(){ printf("%d\n",work()); } int main(){ scanf("%d",&T); while(T--){ init(); input(); solve(); }return 0; }