刚开始正反向dfs,只得了25分,后来参考dalao代码,发现可以将邻接表和领接矩阵相结合,邻接表用于存储图+dfs遍历(因为是有向图),领接矩阵则用于记录顶点与顶点之间的联系(换言之,将有向边转换为无向边存储),最终,如果该结点到其他任意结点都有边,则ans++,输出ans即可。
25分代码
#include<iostream>
#include<vector>
#include<cstdio>
using namespace std;
const int N = 1005;
int n,m,cnt = 0,visit[N]={0};
vector<int> v1[N],v2[N];
void dfs1(int num){
cnt++;
visit[num] = 1;
for(int i = 0; i < v1[num].size(); i++){
if(!visit[v1[num][i]]) dfs1(v1[num][i]);
}
}
void dfs2(int num){
cnt++;
visit[num] = 1;
for(int i = 0; i < v2[num].size(); i++){
if(!visit[v2[num][i]]) dfs2(v2[num][i]);
}
}
int main(){
int a,b,ans = 0;
scanf("%d%d", &n, &m);
for(int i = 0; i < m; i++){
scanf("%d%d", &a, &b);
v1[a].push_back(b);
v2[b].push_back(a);
}
for(int i = 1; i <= n; i++){
cnt = 0;fill(visit,visit+N,0);
dfs1(i);
if(cnt == n) ans++;
}
for(int i = 1; i <= n; i++){
cnt = 0;fill(visit,visit+N,0);
dfs2(i);
if(cnt == n) ans++;
}
printf("%d\n", ans);
return 0;
}
AC代码
#include<iostream>
#include<vector>
#include<cstdio>
using namespace std;
const int N = 1005;
int n,m,cnt = 0,visit[N]={0};
int map[N][N];
vector<int> v[N];
void dfs(int a,int b){
map[a][b] = 1;
map[b][a] = 1;
visit[a] = 1;
for(int i = 0; i < v[a].size(); i++){
if(!visit[v[a][i]]) dfs(v[a][i],b);
}
}
int main(){
int a,b,ans = 0,j;
scanf("%d%d", &n, &m);
for(int i = 0; i < m; i++){
scanf("%d%d", &a, &b);
v[a].push_back(b);
}
for(int i = 1; i <= n; i++){
fill(visit,visit+N,0);
dfs(i, i);
}
for(int i = 1; i <= n; i++){
for(j = 1; j <= n; j++){
if(map[i][j] == 0) break;
}
if(j == n+1) ans++;
}
printf("%d\n", ans);
return 0;
}