题意:给定一个有向图,统计有多少点对u,v满足u可以到达v,且v可以到达u。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 200010,M = 400010;
typedef long long LL;
int e[M],h[N],ne[M],idx;
int re[M],rh[N],rne[M],ridx;
int t;
int n,m;
bool st[N];
int q[N],top;
void add(int a,int b){
e[idx] = b,ne[idx] = h[a],h[a] = idx ++;
re[ridx] = a,rne[ridx] = rh[b],rh[b] = ridx ++;
}
void dfs2(int u){
st[u] = true;
for(int i = rh[u];~i;i = rne[i]){
int j = re[i];
if(!st[j])
dfs2(j);
}
q[++ top] = u;
}
int dfs(int u){
int res = 1;
st[u] = true;
for(int i = h[u];~i;i = ne[i]){
int j = e[i];
if(!st[j])
res += dfs(j);
}
return res;
}
int main(){
scanf("%d",&t);
while(t --){
top = 0,idx = 0,ridx = 0;
memset(h,-1,sizeof h);
memset(rh,-1,sizeof rh);
scanf("%d%d",&n,&m);
memset(st,0,sizeof st);
for(int i = 0;i < m;i ++){
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
}
for(int i = 1;i <= n;i ++){
if(!st[i])
dfs2(i);
}
memset(st,0,sizeof st);
LL ans = 0;
for(int i = top;i >= 1;i --){
if(!st[q[i]]){
int res = dfs(q[i]);
ans += 1ll * res * (res - 1) / 2;
}
}
printf("%lld\n",ans);
}
return 0;
}