from collections import deque
import sys
def get_int():
return int(sys.stdin.readline().strip())
def get_ints():
return map(int,sys.stdin.readline().strip().split())
def get_list():
return list(map(int,sys.stdin.readline().strip().split()))
def get_string():
return sys.stdin.readline().strip()
def dfs(u,n):
q = deque()
visited.clear()
for i in range(n):
par[i] = -1
found = False
q.append(u)
while q and (not found):
node = q.pop()
if (node in visited):
continue
visited.add(node)
for u in adj[node]:
if found:
break
if (u not in visited):
par[u] = node
q.append(u)
elif u!=par[node]:
found=True
while node!=u:
isOnCycle[node]=True
cycle.add(node)
node = par[node]
isOnCycle[u] = True
cycle.add(u)
break
def subSize(u):
val = 1
for v in adj[u]:
if (not isOnCycle[v]):
val+=treeSize(v,u)
return val
def treeSize(root,parent):
q = deque()
q.append(root)
visited.clear()
count= 1
while q:
node = q.popleft()
if node in visited:
continue
visited.add(node)
for u in adj[node]:
if (u in visited) or u==parent:
continue
q.append(u)
count+=1
return count
for _ in range(get_int()):
n = get_int()
lim = n
adj = [[] for _ in range(lim)]
isOnCycle = [False]*lim
cycle = set()
visited = set()
par = [-1]*lim
sub = [-1]*lim
for i in range(n):
adj[i].clear()
isOnCycle[i]=False
sub[i] = -1
cycle.clear()
for _ in range(n):
u,v = get_ints()
u-=1
v-=1
adj[u].append(v)
adj[v].append(u)
dfs(0,n)
ans = n*(n-1)
for u in cycle:
val=subSize(u)
ans = ans - (val*(val-1)//2)
print(ans)
#include <bits/stdc++.h>
using namespace std;
bool x=false;
void cycle(int node,vector<vector<int>>&adj,vector<bool>&vis,stack<int>&q,vector<int>&ans,int&parent,int&d){
vis[node]=true;
q.push(node);
d++;
for(auto it:adj[node]){
if(!vis[it]){
cycle(it,adj,vis,q,ans,node,d);
q.pop();
vis[it]=true;
}
else{
if((it!=parent)&&(!x)){
int xx=it;
stack<int> d=q;
x=true;
while((!d.empty())){
ans.push_back(d.top());
if(d.top()==it) break;
d.pop();
}
break;
}
}
}
}
int main() {
int t;cin>>t;
while(t--){
long long n;cin>>n;
vector<bool> vis(n+1,false);
vector<vector<int>> adj(n+1);
vector<pair<int,int>> edges(n);
for(auto&v:edges) cin>>v.first>>v.second;
for(int j=0;j<n;j++){
int a=edges[j].first,b=edges[j].second;
adj[a].push_back(b);
adj[b].push_back(a);}
vector<int> ans;stack<int> q;
int b=0,k=-1;
cycle(1,adj,vis,q,ans,k,b);x=false;
set<int> s; for(auto it:ans){ s.insert(it);}
for(int j=1;j<=n;j++) adj[j].clear();
for(int j=0;j<n;j++){
int a=edges[j].first,b=edges[j].second;
if(s.find(a)==s.end()||s.find(b)==s.end()){
adj[a].push_back(b);adj[b].push_back(a);
}
}
long long ansx=0;
for(int j=1;j<=n;j++) vis[j]=false;
vector<long long> dx;long long sum=0;
for(int j=1;j<=n;j++){
if(!vis[j]){
int d=0,k=-1;
stack<int> sx;
cycle(j,adj,vis,sx,ans,k,d);x=false;
dx.push_back(d);
sum+=d;
//cout<<d<<" ";
}
}//cout<<endl;
for(auto it:dx){ ansx+=(it*(it-1))/2 + it*(n-it);}
//ansx+=(s.size()*(s.size()-1));
cout<<ansx<<endl;
}
return 0;
}
838A - Binary Blocks | 1515D - Phoenix and Socks |
1624D - Palindromes Coloring | 1552F - Telepanting |
1692G - 2Sort | 1191A - Tokitsukaze and Enhancement |
903A - Hungry Student Problem | 52B - Right Triangles |
1712A - Wonderful Permutation | 1712D - Empty Graph |
1712B - Woeful Permutation | 1712C - Sort Zero |
1028B - Unnatural Conditions | 735B - Urbanization |
746C - Tram | 1278B - A and B |
1353D - Constructing the Array | 1269C - Long Beautiful Integer |
1076A - Minimizing the String | 913C - Party Lemonade |
1313A - Fast Food Restaurant | 681A - A Good Contest |
1585F - Non-equal Neighbours | 747A - Display Size |
285A - Slightly Decreasing Permutations | 515C - Drazil and Factorial |
1151E - Number of Components | 1151F - Sonya and Informatics |
556A - Case of the Zeros and Ones | 867A - Between the Offices |