分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 前端开发

[luogu1197] [JSOI2008]星球大战

发布时间:2023-09-06 02:18责任编辑:沈小雨关键词:暂无标签

传送门

看到联通块,好像跟并查集、强连通分量有关系吧,仔细一看跟哪些点属于哪些块没关系,只关心联通块数量,那么应该可以用并查集做。继续看,这是一道删边的题,好像很难维护删边,我们又知道并查集是可以维护加边的,那么我们就倒过来做好了。

#include <cstdio>#include <cstring>#include <algorithm>#define MAXN 400005struct Node{ ???int u,v;}E[MAXN];struct edge{ ???int v,next;}G[MAXN];int fa[MAXN],vis[MAXN];int ed[MAXN],ans[MAXN];int head[MAXN];int N,M,K,tot=0;int find(int x){ ???return x==fa[x]?x:fa[x]=find(fa[x]);}inline void merge(int u,int v){ ???fa[find(u)] = find(v);}inline void add(int u,int v){ ???G[++tot].v = v ;G[tot].next = head[u];head[u] = tot;}int main(){ ???scanf("%d%d",&N,&M); ???for(register int i=0;i<N;++i){ ???????fa[i] = i; ???} ???std::memset(head,0,sizeof(head)); ???std::memset(vis,0,sizeof(vis)); ???for(register int i=1;i<=M;++i){ ???????scanf("%d%d",&E[i].u,&E[i].v); ???????add(E[i].u,E[i].v); ???????add(E[i].v,E[i].u); ???} ???scanf("%d",&K); ???int count = N-K; ???for(register int i=K;i>=1;--i){ ???????scanf("%d",&ed[i]); ???????vis[ed[i]] = 1; ???} ???for(register int i=1;i<=M;++i){ ???????int u = E[i].u;int v = E[i].v; ???????if(vis[u]||vis[v]||(find(u)==find(v)))continue; ???????merge(u,v); ???????count--; ???} ???ans[0] = count; ???for(register int i=1;i<=K;++i){ ???????vis[ed[i]] = 0; ???????count++; ???????for(register int j=head[ed[i]];j;j=G[j].next){ ???????????int v = G[j].v; ???????????if(!vis[v]&&find(v)!=find(ed[i])){ ???????????????merge(v,ed[i]); ???????????????count--; ???????????} ???????} ???????ans[i] = count; ???} ???for(register int i=K;i>=0;--i){ ???????printf("%d\n",ans[i]); ???} ???return 0;}

[luogu1197] [JSOI2008]星球大战

原文地址:https://www.cnblogs.com/Neworld2002/p/9814046.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved