#include <bits/stdc++.h>
using namespace std;
class Graph{
public:
int n;
int m;
int maxEdges;
bool isDirected;
vector<vector<int>> adj;
// int **adj;
Graph(int nodes, bool isDiGraph) : adj(nodes){
n = nodes;
m = 0;
isDirected = isDiGraph;
maxEdges = isDirected ? n*(n-1) : n*(n-1)/2;
// adj = new int*[n];
// for(int i = 0; i < n; ++i)
// adj[i] = new int[n];
}
void insertEdge(int u, int v){
if(u >= n || v >=n || u < 0 || v < 0){
cout<<"Either of the vertices doesn't exists in the graph.\n";
return;
}
if(m == maxEdges){
cout<<"Maximum allowed edges are already in the graph. Can't insert more.\n";
return;
}
adj[u].push_back(v); ++m;
if(!isDirected && u != v)
adj[v].push_back(u);
}
void deleteEdge(int u, int v){
if(u >= n || v >=n || u < 0 || v < 0){
cout<<"Either of the vertices doesn't exists in the graph.\n";
return;
}
auto itr = find(adj[u].begin(), adj[u].end(), v);
if(itr == adj[u].end()){
cout<<"The edge doesn't exists in the graph.\n";
return;
}
adj[u].erase(itr); --m;
if(!isDirected && u != v){
itr = find(adj[v].begin(), adj[v].end(), u);
adj[v].erase(itr);
}
}
void displayGraph(){
if(!m){
cout<<"The graph is empty!!";
return;
}
cout<<"Total # edges in the graph: "<<m<<"\n";
for(int i = 0; i < n; ++i){
cout<<"The edges from vertex "<<i<<":";
for(auto val: adj[i])
cout<<"->"<<val;
cout<<"\n";
}
}
void dfsRecursiveHelper(int src, stack<int> &st,
vector<vector<int>> &adjList,
vector<bool> &visited, bool &useStack,
vector<int> &ans){
visited[src] = true;
for(auto node: adjList[src]){
// if(!useStack && node == src){
// ans.push_back(node);
// }
// else
if(isSafe(node) && !visited[node]){
dfsRecursiveHelper(node, st, adjList, visited, useStack, ans);
if(useStack){
st.push(node);
}
else{
ans.push_back(node);
}
}
}
}
void dfsRecursive(vector<vector<int>> &adjList,
vector<bool> &visited,
stack<int> &st,
bool &useStack){
int connectedComponents = 0;
vector<int> ans;
int maxCycleSum = INT_MIN;
if(useStack){
for(int i = 0; i < n; ++i){
if(isSafe(i) && !visited[i]){
dfsRecursiveHelper(i, st, adjList, visited, useStack, ans);
st.push(i);
}
}
}
else{
while(!st.empty()){
int i = st.top();
if(isSafe(i) && !visited[i]){
dfsRecursiveHelper(i, st, adjList, visited, useStack, ans);
if(ans.size() > 0){
cout<<"The nodes in strongly connected component "<<++connectedComponents<<": "<<i;
for(auto val: ans)
cout<<"->"<<val;
cout<<"\n";
int s = accumulate(ans.begin(), ans.end(), 0) + i;
if(s > maxCycleSum)
maxCycleSum = s;
cout<<"Cycle sum: "<<s;
cout<<"\n------------------------------------------------------------------\n";
}
ans.clear();
}
st.pop();
}
for(int i = 0; i < n; ++i){
for(auto &node: adjList[i]){
if(visited[node] && node == i){
cout<<"The nodes in strongly connected component(self loop) "<<++connectedComponents<<": "<<i;
cout<<"->"<<node<<"\n";
if(i > maxCycleSum)
maxCycleSum = i;
cout<<"Cycle sum: "<<i;
cout<<"\n------------------------------------------------------------------\n";
}
}
}
}
if(!useStack && connectedComponents){
cout<<"Max cycle sum: "<<maxCycleSum<<"\n";
cout<<"The directed graph has "<<connectedComponents<<" strongly connected components.\n";
}
else if(!useStack){
cout<<"------------------------------------------------------------------\n";
cout<<"The directed graph has no strongly connected components.\n";
cout<<"Max cycle sum: -1\n";
}
}
void findStronglyConnectedComponents(){
/*================ DFS on actual graph ================*/
vector<bool> visited(n, false);
stack<int> st;
bool printVertices = false, useStack = true;
dfsRecursive(adj, visited, st, useStack);
/*================ DFS on actual graph ================*/
/*================ Transpose graph ===============*/
vector<vector<int>> adjTranspose(n);
for(int i=0; i < n; ++i){
for(auto node: adj[i]){
if(isSafe(node))
adjTranspose[node].push_back(i);
}
}
/*================ Transpose graph ===============*/
/*================ DFS on Transpose graph ================*/
printVertices = true, useStack = false;
visited = vector<bool>(n, false);
dfsRecursive(adjTranspose, visited, st, useStack);
/*================ DFS on Transpose graph ================*/
}
bool isSafe(int idx){
return -1 < idx && idx < n;
}
};
int main() {
int t;
cin>>t;
while(t--){
int n, v; cin>>n;
Graph g(n, 1);
for(int i=0; i < n; ++i){
cin>>v;
g.insertEdge(i, v);
}
g.findStronglyConnectedComponents();
cout<<"==================================================================\n";
}
return 0;
}