(tajan+floyd) zoj 3232
When a directed graph is given, we can solve its transitive closure easily using the well-known Floyd algorithm.
But if you're given a transitive closure, can you give a corresponding directed graph with minimal edges?
Input
About 100 test cases, seperated by blank line.
First line of each case is an integer N (1<=N<=200). The following N lines represent the given transitive closure in 0-1 matrix form, each line has N numbers.
Output
For each case, just output the number of minimal edges of a directed graph which has a given transitive closure.
Sample Input
1 1 2 1 0 0 1 2 1 1 1 1 3 1 1 1 0 1 1 0 0 1
Sample Output
0 0 2 2
Hint
Transitive closure can be presented as a matrix T, where Ti,j is true if and only if there is a path from vertex i to j.
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<cstdlib> #include<vector> #include<stack> using namespace std; stack<int> s; vector<int> e[205]; int n,mp[205][205],Dfs[205],low[205],cmp[205][205],use[205],num[205],top,newflag; bool isstack[205]; void init() { memset(num,0,sizeof(num)); memset(isstack,0,sizeof(isstack)); memset(mp,0,sizeof(mp)); memset(cmp,0,sizeof(cmp)); memset(low,0,sizeof(low)); memset(use,0,sizeof(use)); memset(Dfs,0,sizeof(Dfs)); top=0,newflag=0; while(!s.empty()) s.pop(); for(int i=1;i<=n;i++) e[i].clear(); } void tarjan(int u) { Dfs[u]=low[u]=++top; isstack[u]=1; s.push(u); for(int i=0;i<e[u].size();i++) { int v=e[u][i]; if(!Dfs[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(isstack[v]) low[u]=min(low[u],Dfs[v]); } if(Dfs[u]==low[u]) { newflag++; int x; do { x=s.top(); use[x]=newflag; num[newflag]++; s.pop(); isstack[x]=0; }while(x!=u); } } int main() { while(scanf("%d",&n)!=EOF) { int ans=0; init(); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) scanf("%d",&cmp[i][j]); } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(cmp[i][j]&&i!=j) { e[i].push_back(j); } } } for(int i=1;i<=n;i++) { if(!Dfs[i]) tarjan(i); } for(int i=1;i<=n;i++) { for(int j=0;j<e[i].size();j++) { if(use[i]!=use[e[i][j]]&&cmp[i][e[i][j]]) { mp[use[i]][use[e[i][j]]]=1; } } } for(int i=1;i<=newflag;i++) { if(num[i]!=1) ans+=num[i]; } for(int k=1;k<=newflag;k++) { for(int i=1;i<=newflag;i++) { for(int j=1;j<=newflag;j++) { if(mp[i][k]&&mp[k][j]&&mp[i][j]) mp[i][j]=0; } } } for(int i=1;i<=newflag;i++) { for(int j=1;j<=newflag;j++) { if(mp[i][j]) ans++; } } printf("%d\n",ans); } return 0; }