逆向并查集(zoj 3261,hdoj 4496)

zoj 3261 Connections in Galaxy War

题目大意: 银河中一些星球之间有通道可以联系,然而另一个维度的怪物将某些联系破坏了。因此当有些星球需要帮助时,就需要判断一下能不能找到一个直接或间接联系的星球,并且这个星球的力量是与该星球连接的所有星球中最大的。如果有这么一个星球,则输出该星球的编号,如果有多个星球是最大的,输出编号最小的那个。如果找不到这样的星球,则输出“-1”。
在输入中,首先输入星球个数n,第二行是n个数,表示每个星球的力量。下一行是一个整数m,表示所有的联系个数,下面是m行,每行两个整数,表示哪两个星球有联系。下一行是一个整数q,表示处理个数,有两种情况:
第一种是:destroy a b 表示摧毁a,b之间的联系
第二种是:query a 表示询问a星球能否得到帮助

题解: 我们所熟悉的并查集只有加边的作用,并查集并没有删除边的作用。一开始拿到这个题一脸懵逼 ,无从下手,然后去看dalao代码,发现这是逆向并查集,正向是删边,如果反向来看的话就是加边了啊,这不正是并查集吗?
这里的逆向的意思是,先离线处理所有的操作,然后再逆向处理操作,在读入的时候,所有被删除的边先不要添加到并查集里,逆向处理时,遇到“destroy”时,将这个边加入到并查集中。
dalao的做法是用map存储边与编号的关系,然后再用used数组记录哪条边是要被删除的,很巧妙的将编号与边结合在一起。

AC代码:

#include <iostream>
#include <map>
#include <string.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
const int MAX=10001;
int power[MAX];//每个行星的战斗力
map<int,int>mp[MAX];//存边,以及边的编号
int used[2*MAX];//与map相结合,记录哪条边需要删除
int parent[MAX];
int ans[5*MAX];
int n;
struct edge//记录边,方便通过下标查询连接两个边的节点
{
   
    int x;
    int y;
}edges[2*MAX];
struct ques//记录问题,如果是destroy ,mark 记为1,如果是query,mark记为0
{
   
    int mark;
    int x;
    int y;
}que[5*MAX];
struct re//要求的最大力量和最小的编号
{
   
    int height;
    int num;
}res[MAX];
void init()//初始化
{
   
    memset(used,0,sizeof(used));
    for(int i=0;i<n;i++)
    {
   
        parent[i]=i;
        res[i].height=power[i];
        res[i].num=i;
        mp[i].clear();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值