题目描述
A 国有 n 个城市从 1 到 n 编号,在城市间有 m 条单向航线。 A 国首都位于编号为 w 的城市,现在 A 国政府希望在首都召开会 议,就想要让各地人民都能够通过若干条航线到达首都,那么至少需 要新建多少条航线?(可能有重边和自环)
输入输出格式
输入格式:
第一行三个整数 n,m,w 接下来 m 行,每行两个整数 xi,yi,表示存在一条从 xi 到 yi 城市 的单向航线
输出格式:
一个整数表示最小需要新建多少条航线
输入输出样例
说明
对于 20%的数据 n<=10 m<=10 对于 40%的数据 n<=100 m<=100 对于 100%的数据 n<=10^6 m<=10^6
老师出的毒瘤题
本来想让我们写tarjin,结果没人写(没人会写)
题目给有向图,先反着建图,反着扫把能直接到终点的点标记
然后正这扫,一个点正反都没扫,就进深搜,只扫着个点连着的一个点(我也只记录了一个点),一直扫下去,如果扫到以前扫过的点,答案数就不用+1了,不然答案数+1
扫的过程中的点都标记为扫过
为什么只扫一个
1.扫的这个点能到终点或以前把他和终点建过边,高兴地返回
2。扫的这个天目前还不能到终点,那就标记为能到终点,答案加一,虽然按最开始扫的点不是最优解,但全局上不变,你以后肯定还得连
#include<bits/stdc++.h>
using namespace std;
int n,m,s,x,y,ans,a[1000001];
vector<int>f[1000001];
bool sao[1000001],zou[1000001];
queue<int>q;
void spfa()
{
q.push(s);
sao[s]=1;
while(q.empty()==0)
{
int u=q.front();q.pop();
for(int i=0;i<f[u].size();i++)
{
int w=f[u][i];
if(sao[w]==0)
{
sao[w]=1;
q.push(w);
}
}
}
}
bool dfs(int k)
{
if(a[k]==0)
{
return 0;
}
if(zou[a[k]]==0)
{
zou[a[k]]=1;
dfs(a[k]);
}
else
return 1;
}
int main()
{
cin>>n>>m>>s;
for(int i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
if(x!=y)
{
f[y].push_back(x);
a[x]=y;
}
}
spfa();
for(int i=1;i<=n;i++)
{
if(sao[i]==0&&zou[i]==0)
{
zou[i]=1;
if(dfs(i)==0)
{
ans++;
}
}
}
cout<<ans;
}