#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;
}