星球大战 并查集!!!

Sample Input

8 13 0 1 1 6 6 5 5 0 0 6 1 2 2 3 3 4 4 5 7 1 7 2 7 6 3 6 5 1 6 3 5

Sample Output

1 1 1 2 3 3

#include <bits/stdc++.h>
using namespace std;

int tot,n,m,d,f[400001],head[400001],q[400001],ans[400001],cnt=1;

bool used[400001], des[400001];
struct data{int to,next;}e[400001]; //next是

int find(int x){return x==f[x]?x:f[x]=find(f[x]);}

void ins(int u,int v) {//存图
    e[++cnt].to=u; e[cnt].next=head[v]; head[v]=cnt;
    e[++cnt].to=v; e[cnt].next=head[u]; head[u]=cnt;
}

void add(int x) {
    int i=head[x],p=find(x),q; //p是x的父节点,
    while(i) {
        if(used[e[i].to]) { // 如果该点被使用过
            q=find(e[i].to); //q就为e[i].to的父节点
            if(p!=q){f[q]=p;tot--;} //如果两个父节点不同(不是它本身) p为q的父节点 tot自减
        }
        i=e[i].next; //i为与它相邻的点
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++) f[i]=i;

    for(int i=1;i<=m;i++) {
        int x,y;
        scanf("%d%d",&x,&y);
        ins(x,y);
    }

    scanf("%d",&d); // d是进行的操作次数
    for(int i=1;i<=d;i++) {
        scanf("%d",&q[i]);
        des[q[i]]=1; // 记录被摧毁的星球
    }

    for(int i=0;i<n;i++) {
        if(!des[i]) { //如果该星球没有被摧毁
            tot++;  //记录没有被摧毁的星球个数
            add(i); //传入add函数(即merge函数进行并查集构图
            used[i]=1; //i已经进入图中
        }
    }
    ans[d+1]=tot;  //此时tot是除去被摧毁星球的连通块数目

    for(int i=d;i>0;i--) {
        tot++; // 摧毁一个星球首先默认会导致连通块++
        add(q[i]); //将被摧毁的星球补回去
        used[q[i]]=1; //q[i]被使用
        ans[i]=tot;  // tot此时为该状态下的连通块数
    }

    for(int i=1;i<=d+1;i++)printf("%d\n",ans[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/lightac/p/10721378.html

时间: 2024-11-09 00:59:07

星球大战 并查集!!!的相关文章

【JSOI2008】星球大战[并查集]

[JSOI2008]星球大战 决定再做一道并查集水题.... 正难则反 现将要攻击的星球都读入 然后记录已损坏 再将能连的都连上 然后倒着做 就是套路了QAQ 第一次交的代码死于没有认真读题...编号是从0开始的 #include<bits/stdc++.h> using namespace std; const int N=4e5+5,M=2e5+5,inf=0x3f3f3f3f,P=19650827; int n,m,k,cnt=0,ans[N],a[N]; bool broken[N];

BZOJ 1015 星球大战 并查集+离线

这道题说来真是艰辛,从一开始的RE,到RE,到刚刚的WA,再到AC. 这只能说明我进步的历程,还有我需要不断的加强努力.这道题思路不难,从很久前在黑书中并查集一节就能找到解题的踪影,因为并查集只能并,分不了,所以我们就得离线,倒过来写.只不过这道题真的得审好题目,它问的是剩下的星球中有多少个连通分量,不要搞错了.大概就是这个样子了,加油. 1 #include<cstdio> 2 #include<iostream> 3 #define rep(i,j,k) for(int i=

[JSOI2008]星球大战——并查集+逆向思维

题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快帝国又重新造出了他的超级武器.凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球.由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来.现在,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度

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

1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 5253  Solved: 2395[Submit][Status][Discuss] Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快帝国又重

【并查集】星球大战starwar

BZOJ1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 6407  Solved: 2973[Submit][Status][Discuss] Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快

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

1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 3895  Solved: 1750[Submit][Status][Discuss] Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快帝国又重

【并查集】bzoj1015 [JSOI2008]星球大战starwar

倒着处理删点,就变成了加点,于是并查集. #include<cstdio> using namespace std; #define N 400001 int fa[N],kill[N],rank[N],n,m,q; bool hav[N]; int next[N],first[N],v[N],en,x,y,anss[N],cnt; void AddEdge(int U,int V) { v[++en]=V; next[en]=first[U]; first[U]=en; } int find

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

很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快帝国又重新造出了他的超级武器.凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球.由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来.现在,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每一次

BZOJ 1015: [JSOI2008]星球大战starwar【并查集】

题目可以表述成:给定一个无向图G,每次删除它的一个点和与点相关的边集,每次询问该操作后图G的连通度(连通分量的个数).和上一题一样都是考察逆向思维,虽然删除点的做法不会,但是每次加点后询问连通度却是并查集的经典用法,所以答案可以逆过来推,具体做的时候每次加入一个点,将所有和这个点有边相连的点集合并,然后输出当前有多少个集合.细节部分需要注意的是由于点的数量十分庞大,邻接表是十分有必要的 #include<iostream> #include<cstdio> #include <