题目链接:https://vjudge.net/contest/236513#problem/E
大意:给你n条边的关系,输入的第一个只指向第一个,然后让你判断要想从指定的点到达剩下的所有的点,问你最少需要添加多少条边才符合要求。
思路:首先使用tarjan算法进行染色,缩点。到最后判断 缩减后 入度为零的不含有城市中心的强连通子图的个数就可以了!!!
原因,染完色之后,如果有入度为0的强连通子图,那么这个点就可能符合,然后吧满足这些条件的记录一下。注意,在累加 的时候,不能将入度为0的含有城市中心的强连通子图计算在内,因为这个图中,有城市中心的强连通图中,这个图中的其他所有的点都能由城市中心到达,所以不用累加。
代码如下:
#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
# define maxn
vector<int >wakaka[maxn];
map<int,int>p;
stack<int>q;
int dfn[maxn],low[maxn],vis[maxn];
int out[maxn],cnt[maxn],color[maxn],in[maxn];
int num,ans;
void tarjan(int u)
{
vis[u]=;
q.push(u);
low[u]=dfn[u]=++num;
int len=wakaka[u].size();
for(int i=; i<len; i++)
{
int v=wakaka[u][i];
if(vis[v]==)
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
if(vis[v]==)
{
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u])
{
ans++;
int top;
do
{
top=q.top();
q.pop();
vis[top]=-;
color[top]=ans;
}
while(top!=u);
}
}
int main()
{
int n,m,t;
while(cin>>n>>m>>t)
{
num=ans=;
memset(vis,,sizeof(vis));
memset(cnt,,sizeof(cnt));
memset(out,,sizeof(out));
memset(in,,sizeof(in));
memset(color,,sizeof(color));
while(!q.empty())q.pop();
for(int i=; i<=n; i++)
{
wakaka[i].clear();
}
p.clear();
for(int i=; i<=m; i++)
{
int u,v;
cin>>u>>v;
p[u]++;
p[v]++;
wakaka[u].push_back(v);
}
for(int i=; i<=n; i++)
{
if(vis[i]==)
tarjan(i);
}
//cout<<color[1]<<endl<<color[2]<<endl;
for(int i=; i<=n; i++)
{
int len=wakaka[i].size();
for(int j=; j<len; j++)
{
if(color[i]!=color[wakaka[i][j]])
{
in[color[i]]++;
out[color[wakaka[i][j]]]++;
}
}
cnt[color[i]]++;
}
int t1=,t2=;
for(int i=; i<=ans; i++)
{
if(in[i]==)
t1++;
if(out[i]==&&i!=color[t])
{
t2++;
}
}
cout<<t2<<endl;
//else {
//cout<<max(t1,t2)<<endl;
//}
//}
}
return ;
}