第一下学期了,学院都在备战ccf-csp考试,所以就去刷了往年的真题,水平有限,可能解法不好,敬请见谅!
我刚好在学习图论的知识,就找了这题先做,感觉凭借着莽夫的勇气,我竟然一次就满分了,惊讶;
下面是思路:
1、用spfa求出所以点互相能否到达对方;
2、两重循环处理,使一个方向能到的,另一个方向也能
到;
3、然后就是输出答案了;
废话不多说,贴上代码://100分
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
vector<pair<int,int> >E[1005];//习惯用stl
int d[1005][1005];//保存下每个点到另一个点是否通行;
bool v[1005];
void init()//初始化
{
memset(d,inf,sizeof(d));
return ;
}
queue<int>q;
int main()
{
int n,m;
cin>>n>>m;
init();
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
E[a].push_back(make_pair(b,0));
}
for(int i=1;i<=n;i++)// 用spfa求出dis数组
{
memset(v,0,sizeof(v));
while(!q.empty())q.pop();
q.push(i);
d[i][i]=0;
v[i]=1;
while(!q.empty())
{
int now=q.front();
q.pop();
v[now]=0;
for(int j=0;j<E[now].size();j++)
{
int vv=E[now][j].first;
if(d[i][vv]>d[i][now]+E[now][j].second)
{
d[i][vv]=d[i][now]+E[now][j].second;
if(!v[vv]){
q.push(vv);
v[vv]=1;
}
}
}
}
}
int sum=0;
for(int i=1;i<=n;i++)//循环一遍,把能传递信息的反向也行,但是不能一开始就用无向边;
for(int j=1;j<=n;j++)
if(d[i][j]==0)d[j][i]=0;
for(int i=1;i<=n;i++)//然后就是依次搜索能全部到达的
{
int flag=0;
for(int j=1;j<=n;j++)
{
if(d[i][j]==inf){
flag=1;
break;
}
}
if(!flag)sum++;
}
cout<<sum<<endl;
return 0;
}