分别保存两个图,第一个图表示u大于v,第二个图为反向图,表示u小于v.
然后用floyd或者dfs求出这两个图各个顶点的能到达的结点数量,如果某个点数量大于n/2说明这个数不可能成为中位数.
#include <iostream>
#include <cstdio>
#include <memory.h>
const int maxn = 105;
int g1[maxn][maxn], g2[maxn][maxn], n, m;
bool f[maxn];
void floyd(int g[][maxn]){
for(int k = 1; k <= n; ++k){
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
if(g[i][k] && g[k][j]){
g[i][j] = 1;
}
}
}
}
}
void solve(int g[][maxn]){
for(int i = 1; i <= n; ++i){
int cnt = 0;
for(int j = 1; j <= n; ++j){
if(g[i][j])cnt++;
}
if(cnt > n/ 2){
f[i] = 1;
}
}
}
int main(){
int T;
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
memset(f, 0, sizeof(f));
memset(g1, 0, sizeof(g1));
memset(g2, 0, sizeof(g2));
for(int i = 0; i < m; ++i){
int u, v;
scanf("%d%d", &u, &v);
g1[u][v] = 1;
g2[v][u] = 1;
}
floyd(g1);
floyd(g2);
solve(g1);
solve(g2);
int ans = 0;
for(int i = 1; i <= n; ++i){
if(f[i]){
ans++;
}
}
printf("%d\n",ans);
}
}
#include <iostream>
#include <cstdio>
#include <memory.h>
const int maxn = 101;
int g1[maxn][maxn], g2[maxn][maxn], n, m;
int bCnt[maxn], lCnt[maxn];
bool vis[maxn];
int dfs_1(int u){
int cnt = 0;
vis[u] = 1;
for(int v = 1; v <= n; ++v){
if(g1[u][v] && !vis[v]){
cnt += dfs_1(v);
}
}
return cnt + 1;
}
int dfs_2(int u){
int cnt = 0;
vis[u] = 1;
for(int v = 1; v <= n; ++v){
if(g2[u][v] && !vis[v]){
cnt += dfs_2(v);
}
}
return cnt + 1;
}
int main(){
int T;
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
memset(g1, 0, sizeof(g1));
memset(g2, 0, sizeof(g2));
for(int i = 0; i < m; ++i){
int u, v;
scanf("%d%d", &u, &v);
g1[u][v] = 1;
g2[v][u] = 1;
}
for(int i = 1; i <= n; ++i){
memset(vis, 0, sizeof(vis));
lCnt[i] = dfs_1(i) - 1;
}
for(int i = 1; i <= n; ++i){
memset(vis, 0, sizeof(vis));
bCnt[i] = dfs_2(i) - 1;
}
int ans = 0;
for(int i = 1; i <= n; ++i){
if(bCnt[i] > n / 2 || lCnt[i] > n / 2){
ans++;
}
}
printf("%d\n",ans);
}
}