题目链接:点击查看
题目大意:一个学校连接在一个计算机网络上,学校之间存在软件支援协议,每个学校都有它应支援的学校名单(学校A支援学校B,并不表示学校B一定支援学校A)。当某校获得一个新软件时,无论是直接获得还是通过网络获得,该校都应立即将这个软件通过网络传送给它应支援的学校,因此,一个新软件若想让所有学校都能使用,只需将其提供给一些学校即可:
- 最少需要将一个新软件直接提供给多少个学校,才能使软件能够通过网络被传送到所有学校?
- 最少需要添加几条新的支援关系,使得将一个新软件提供给任何一个学校,其他所有学校就都可以通过网络获得该软件?
题目分析:题目给出的是有向图,对于这个题目而言,首先强连通缩一下点,这样每一个集合中的点;两两都可以互相到达,相对来说无法到达的就只有入度为0的点对应的集合了,统计一下有多少个入度为0的集合,就是第一问的答案了,对于第二问而言,为了让整个集合成为强连通图,我们必须让所有点的入度和出度都不为0,所以答案就是入度为0的集合的数量和出度为0的集合的数量中的较大值了,不过这个题目有个小坑需要特判一下,如果一开始整个图就是一个强联通图的话,那么答案需要输出1 0,而不是1 1
代码:
#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
const int N=110;
const int M=N*N;
struct Egde
{
int to,next;
}edge1[M],edge2[M];
int head1[N],head2[N],low[N],dfn[N],c[N],Stack[N],num,cnt,cnt2,cnt1,dcc,n,m,top,in[N],out[N];
bool ins[N];
vector<int>scc[N];
void addedge1(int u,int v)
{
edge1[cnt1].to=v;
edge1[cnt1].next=head1[u];
head1[u]=cnt1++;
}
void addedge2(int u,int v)
{
edge2[cnt2].to=v;
edge2[cnt2].next=head2[u];
head2[u]=cnt2++;
}
void tarjan(int u)
{
dfn[u]=low[u]=++num;
Stack[++top]=u;
ins[u]=true;
for(int i=head1[u];i!=-1;i=edge1[i].next)
{
int v=edge1[i].to;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(ins[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
cnt++;
int v;
do
{
v=Stack[top--];
ins[v]=false;
c[v]=cnt;
scc[cnt].push_back(v);
}while(u!=v);
}
}
void solve()
{
for(int i=1;i<=n;i++)//缩点
if(!dfn[i])
tarjan(i);
}
void build()//缩点+连边
{
solve();
for(int i=1;i<=n;i++)
{
for(int j=head1[i];j!=-1;j=edge1[j].next)
{
int u=i;
int v=edge1[j].to;
if(c[u]!=c[v])
addedge2(c[u],c[v]);
}
}
}
void init()
{
for(int i=0;i<N;i++)
scc[i].clear();
top=cnt=cnt1=cnt2=num=dcc=0;
memset(head2,-1,sizeof(head2));
memset(head1,-1,sizeof(head1));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(c,0,sizeof(c));
memset(ins,false,sizeof(ins));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
}
int main()
{
// freopen("input.txt","r",stdin);
// ios::sync_with_stdio(false);
while(scanf("%d",&n)!=EOF)
{
init();
for(int i=1;i<=n;i++)
{
int to;
while(scanf("%d",&to)!=EOF&&to)
addedge1(i,to);
}
build();
for(int i=1;i<=cnt;i++)
{
for(int j=head2[i];j!=-1;j=edge2[j].next)
{
int u=i;
int v=edge2[j].to;
if(u!=v)
{
in[v]++;
out[u]++;
}
}
}
int ans1=0,ans2=0;
for(int i=1;i<=cnt;i++)
{
if(!in[i])
ans1++;
if(!out[i])
ans2++;
}
if(cnt>1)
printf("%d\n%d\n",ans1,max(ans1,ans2));
else
printf("1\n0\n");
}
return 0;
}
来源:CSDN
作者:Frozen_Guardian
链接:https://blog.csdn.net/qq_45458915/article/details/103680932