P2746 [IOI 1996 / USACO5.3] 校园网 Network of Schools题解
P2746 [IOI 1996 / USACO5.3] 校园网 Network of Schools
题目描述
有一些学校会向其他学校分享软件,即如果这个学校得到了软件,那么在分享列表中的学校也会得到软件。注意这种关系是单向的,即如果 aaa 在 bbb 的列表中,那么 bbb 不一定在 aaa 的列表中。
现在,你需要向其中一些学校下发新软件。为了节约下发软件的成本,你需要回答以下两个问题。
- 至少需要向几个学校下发新软件,可以使得所有学校均获得新软件。
- 定义一次扩展为在某个学校的分享列表中增加一个学校。至少需要进行几次扩展,才可以使得无论对哪个学校仅下发一次软件就可以使得所有学校获得新软件。
两个问题相互独立。
输入格式
输入文件的第一行包括一个正整数 NNN,表示学校数目。学校的编号为数字 111 到 NNN。
接下来 NNN 行,每行都表示一个分享列表,第 i+1i+1i+1 行为学校 iii 的分享列表中的学校编号。每个列表用 000 结束,空列表只用一个 000 表示。
输出格式
你的程序应该在输出文件中输出两行。
第一行应该包括一个正整数,表示问题 111 的解。
第二行应该包括一个非负整数,表示问题 222 的解。
输入输出样例 #1
输入 #1
5
2 4 3 0
4 5 0
0
0
1 0
输出 #1
1
2
说明/提示
2≤N≤1002 \le N \le 1002≤N≤100。
题目翻译来自 NOCOW。
思路
参照了luogu上的题解。
代码见下
#include<bits/stdc++.h>
using namespace std;
long long a,b;
long long n,m,aa,bb,dfn[200005],low[200005],st[200005],n2=0,ss=0,s2[200005],df[200005],fd[200005],fd2[200005],db=0,bd=0,de[200005];
vector<long long> v[200005];
inline void abc(long long a1){
low[a1]=dfn[a1]=++n2;
st[++st[200004]]=a1;
de[a1]=1;
//cout<<st[200004]<<" "<<st[st[200004]]<<endl;
for(int i=0;i<v[a1].size();i++){
long long tt=v[a1][i];
if(de[tt]==1){
low[a1]=min(low[a1],dfn[tt]);
}
else if(de[tt]==0){
abc(tt);
low[a1]=min(low[a1],low[tt]);
}
}
if(low[a1]==dfn[a1]){
ss++;
s2[a1]=ss;
df[ss]=1;
while(st[st[200004]]!=a1){
//cout<<st[200004]<<" "<<st[st[200004]]<<endl;
s2[st[st[200004]]]=ss;
de[st[st[200004]]]=-1;
st[200004]--;
df[ss]++;
}
//cout<<st[200004]<<" "<<st[st[200004]]<<" "<<a1<<endl;
de[st[st[200004]]]=-1;
st[200004]--;
}
//cout<<a1<<" "<<v[a1].size()<<" "<<st[200004]<<endl;
return ;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
while(cin>>aa){
if(aa==0){
break;
}
v[i].push_back(aa);
}
//v[i].push_back(i);
}
for(int i=1;i<=n;i++){
if(dfn[i]==0){
//cout<<"ddddddddddddddddddddddddddd"<<i<<endl;
abc(i);
}
}
for(int i=1;i<=n;i++){
for(int j=0;j<v[i].size();j++){
if(s2[i]!=s2[v[i][j]]){
if(s2[i]==0){
//cout<<i<<endl;
//cout<<st[200004]<<endl;
}
fd[s2[v[i][j]]]++;
fd2[s2[i]]++;
}
}
}
for(int i=1;i<=ss;i++){
if(fd[i]==0){
bd++;
}
if(fd2[i]==0){
db++;
}
}
if(ss==1){
cout<<1<<endl<<0<<endl;
return 0;
}
cout<<bd<<endl<<max(db,bd)<<endl;
return 0;
}

浙公网安备 33010602011771号