P1197 [JSOI2008]星球大战 并查集的逆向思维+链式前向星
Posted 钟钟终
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1197 [JSOI2008]星球大战 并查集的逆向思维+链式前向星相关的知识,希望对你有一定的参考价值。
P1197 [JSOI2008]星球大战
https://www.luogu.com.cn/problem/P1197
我真的心态崩了,找了三个小时才发现错误在哪里。我的习惯是从1开始记录数据,一直就超时,怎么都超时,但还是能过几组样例,我以为是算法问题,没想到是head[0]没更新成-1,只要u的位置上出现0,第一组的cnt直接存成0。本题星球是从0到n-1编号的。。。。。
啊啊啊啊,好烦,浪费了这么久,好在是发现错哪了,交了整整两页才发现。
真的巨坑,巨坑,好大的陷阱!!!我说题解为什么从0开始记录数据,原来就是去避免链式前向星存在的这个陷阱。
表示没有,可用0或者-1来表示,head是用来表示变得下标
如果初始化为0,那么head[0]是不能保存信息的;
如果初始化成-1,一定要记得head[0]=-1;
#include <bits/stdc++.h>
using namespace std;
const int maxn=4e5+5;
struct node
int from,to,nxt;
e[maxn];
int f[maxn],n,m,ans,p[maxn],q[maxn],cnt,k,total,head[2*maxn];
bool vis[maxn];
inline void add_edge(int u,int v)
e[++cnt].to=v;
e[cnt].from=u;
e[cnt].nxt=head[u];
head[u]=cnt;
int r_find(int x)
if(x!=f[x])
f[x]=r_find(f[x]);
return f[x];
inline void mg(int x,int y)
int fx,fy;
fx=r_find(x);fy=r_find(y);
if(fx!=fy)
f[fx]=fy;
int main()
head[0]=-1;
scanf("%d%d",&n,&m);
for(register int i=1;i<=n;i++)
f[i]=i,head[i]=-1;
for(register int i=1;i<=m;i++)
int x,y;scanf("%d%d",&x,&y);
add_edge(x,y);add_edge(y,x);
scanf("%d",&k);
for(register int i=1;i<=k;i++)
register int x;scanf("%d",&x);
vis[x]=1;p[i]=x;
total=n-k;
for(register int i=1;i<=2*m;i++)
if(!vis[e[i].from]&&!vis[e[i].to])
int fx=r_find(e[i].from),fy=r_find(e[i].to);
if(fx!=fy)
f[fx]=fy;total--;
q[k+1]=total;
for(register int i=k;i>=1;i--)
register int u=p[i];
total++;
vis[u]=0;
for(register int j=head[u];j!=-1;j=e[j].nxt)
register int fx=r_find(u),fy=r_find(e[j].to);
if(!vis[e[j].to]&&fx!=fy)
total--;
f[fx]=fy;
q[i]=total;
for(register int i=1;i<=k+1;i++)
printf("%d\\n",q[i]);
return 0;
以上是关于P1197 [JSOI2008]星球大战 并查集的逆向思维+链式前向星的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 1015[JSOI2008]星球大战starwar - 并查集