P1197 [JSOI2008] 星球大战
P1197 [JSOI2008] 星球大战
题目简述
对于n个的点,他们之间有m条边,连接起来的点可以组成连通块,求每次破环一个点后剩余连通块个数
思路
还是不错的一道题,这题可以用并查集来做,正着做肯定行不通,所以我们倒着来建边,对于每次新加入的一个点,我们用链式前向星把他所连接的边都找出来,能加的都尽量加进去,再用并查集判断是不是在连通块里就可以出答案了qwq
BTW, 为什么数组开小了是会WA而不是RE啊qwq,害得我 debug 半天😧
代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
struct Edge{
int _next,_to;
}e[N*2];
struct Node{
int x,y;
}s[2*N];
int fa[2*N],vis[N*2],A[N*2];
int head[N*2],tot,kk[N*2];
int get_fa(int x){
return (fa[x]==x)?x:(fa[x]=get_fa(fa[x]));
}
void add_edge(int u,int v){
e[++tot]._next=head[u];
e[tot]._to=v;
head[u]=tot;
}
int main(){
int n,m,k,ans;
cin>>n>>m;
for(int i=0;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
add_edge(x,y);
add_edge(y,x);
s[i].x=x;s[i].y=y;
}
cin>>k;
for(int i=1;i<=k;i++){
int x;
cin>>x;
kk[i]=x;
vis[x]=1;
}
int kdl=k+1;
ans=n-k;
for(int i=1;i<=m*2;i++){
if(vis[s[i].x]==0&&vis[s[i].y]==0){
int fx=get_fa(s[i].x),fy=get_fa(s[i].y);
if(fx==fy)continue;
fa[fx]=fy;
ans--;
}
}
A[kdl--]=ans;
for(int i=k;i>=1;i--){
ans++;
vis[kk[i]]=0;
for(int j=head[kk[i]];j;j=e[j]._next){
int v=e[j]._to;
if(vis[kk[i]]==0&&vis[v]==0){
int fx=get_fa(kk[i]),fy=get_fa(v);
if(fx==fy)continue;
fa[fx]=fy;ans--;
}
}
A[kdl--]=ans;
}
for(int i=1;i<=k+1;i++)cout<<A[i]<<endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】