P2002 消息扩散题解
P2002 消息扩散
题目背景
本场比赛第一题,给个简单的吧,这 100 分先拿着。
题目描述
有 nnn 个城市,中间有单向道路连接,消息会沿着道路扩散,现在给出 nnn 个城市及其之间的道路,问至少需要在几个城市发布消息才能让这所有 nnn 个城市都得到消息。
输入格式
第一行两个整数 n,mn, mn,m,表示 nnn 个城市,mmm 条单向道路。
以下 mmm 行,每行两个整数 b,eb, eb,e 表示有一条从 bbb 到 eee 的道路,道路可以重复或存在自环。
输出格式
一行一个整数,表示至少要在几个城市中发布消息。
输入输出样例 #1
输入 #1
5 4
1 2
2 1
2 3
5 1
输出 #1
2
说明/提示
【样例解释 #1】
样例中在 4,54, 54,5 号城市中发布消息。
【数据范围】
对于 20%20 \%20% 的数据,n≤200n \le 200n≤200;
对于 40%40 \%40% 的数据,n≤2000n \le 2000n≤2000;
对于 100%100 \%100% 的数据,1≤n≤1051 \le n \le {10}^51≤n≤105,1≤m≤5×1051 \le m \le 5 \times {10}^51≤m≤5×105。
思路
直接 tarjan 即可。
对于此题,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>>m;
for(int i=1;i<=m;i++){
cin>>aa>>bb;
v[aa].push_back(bb);
}
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;
return 0;
}
cout<<bd<<endl;
return 0;
}
#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>>m;
for(int i=1;i<=m;i++){
cin>>aa>>bb;
v[aa].push_back(bb);
}
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;
return 0;
}
cout<<bd<<endl;
return 0;
}

浙公网安备 33010602011771号