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]星球大战 并查集的逆向思维+链式前向星的主要内容,如果未能解决你的问题,请参考以下文章

P1197 [JSOI2008]星球大战

并查集的离线搜索([JSOI2008]星球大战)

bzoj 1015[JSOI2008]星球大战starwar - 并查集

JSOI2008星球大战[并查集]

BZOJ 1015 [JSOI2008]星球大战starwar

BZOJ1015[JSOI2008]星球大战starwar[并查集]