P2812 校园网络【[USACO]Network of Schools加强版】题解
P2812 校园网络【[USACO]Network of Schools加强版】
题目背景
浙江省的几所 OI 强校的神犇发明了一种人工智能,可以 AC 任何题目,所以他们决定建立一个网络来共享这个软件。但是由于他们脑力劳动过多导致全身无力身体被♂掏♂空,他们来找你帮助他们。
题目描述
共有 nnn 所学校 (1≤n≤10000)(1 \leq n \leq 10000)(1≤n≤10000) 已知他们实现设计好的网络共 mmm 条线路,为了保证高速,网络是单向的。现在请你告诉他们至少选几所学校作为共享软件的母机,能使每所学校都可以用上。再告诉他们至少要添加几条线路能使任意一所学校作为母机都可以使别的学校使用上软件。
输入格式
第一行一个正整数 nnn。
接下来 nnn 行每行有若干个整数,用空格隔开。
第 i+1i+1i+1 行,每行输入若干个非零整数 xxx,表示从 iii 到 xxx 有一条线路。以 000 作为结束标志。
输出格式
第一行一个整数,表示至少选几所学校作为共享软件的母机,能使每所学校都可以用上。
第二行一个整数,表示至少要添加几条线路能使任意一所学校作为母机都可以使别的学校使用上软件。
输入输出样例 #1
输入 #1
5
2 0
4 0
5 0
1 0
0
输出 #1
2
2
说明/提示
POJ 原题。数据扩大了 100100100 倍。
$1 \leq $ 边数 ≤5000000\leq 5000000≤5000000,1≤n≤100001 \leq n \leq 100001≤n≤10000 。
实际上,1≤n≤100001 \leq n \leq 100001≤n≤10000,$1\le $ 边数 ≤50000\le 50000≤50000。
思路
直接tarjan 即可。
代码见下
#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号