专栏文章
题解:AT_abc401_e [ABC401E] Reachable Set
AT_abc401_e题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mipmtuna
- 此快照首次捕获于
- 2025/12/03 14:34 3 个月前
- 此快照最后确认于
- 2025/12/03 14:34 3 个月前
思路
看到好多大佬都用了并查集来做,小蒟蒻膜拜,只能给出一个奇奇怪怪的做法。
考虑递增枚举 正向加点,可以发现如果这张图满足要求,第 个点的来源必定小于 。所以可以在每次加点的时候把与它相连接的点记下来。
如果第 个点没有被记下来,则说明无法完成,输出 。
否则,还需要查看是否一到 全能被到达。可以发现之前没被收录的那些点只能通过点 进行拓展。所以,从 跑 dfs。注意,大于 的点不跑。最后查看是否所有点都被收录了。
答案就是被收录点集的大小减去 。
AC Code:
CPP#include<bits/stdc++.h>
using namespace std;
long long n,m,mp[200005],ans;
vector<long long>poi[200005];
inline void dfs(long long now,long long lm){
for(int i=0;i<poi[now].size();i++){
if(mp[poi[now][i]]==0){
ans++;
mp[poi[now][i]]=1;
if(poi[now][i]<=lm)dfs(poi[now][i],lm);
}
}
}
int main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=m;i++){
long long a,b;
scanf("%lld%lld",&a,&b);
poi[a].push_back(b);
poi[b].push_back(a);
}
mp[1]=1;
ans=1;
for(int i=0;i<poi[1].size();i++){
mp[poi[1][i]]=1;
ans++;
}
printf("%lld\n",ans-1);
long long last=1;//优化,只用从上一个成功的 k 往下 check 即可。
for(int i=2;i<=n;i++){
if(mp[i]==1){
dfs(i,i);
long long flag=1;
for(int j=last;j<=i;j++){//优化
if(mp[j]==0){
flag=0;
break;
}
}
if(flag==1)printf("%lld\n",ans-i),last=i;
else printf("-1\n");
}
else{
printf("-1\n");
}
}
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...