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();
}
}

最低0.47元/天 解锁文章
352

被折叠的 条评论
为什么被折叠?



