这两道题长得差不多,都有分裂集合的操作,都是先将所有操作离线,然后从最后一步开始倒着模拟,这样一来,分裂就变成合并,也就是从打击以后最终的零散状态,一步步合并,回到最开始所有星球都被连为一个整体的状态,这就能套并查集了。中途的询问结果用栈存下来,输出的时候一个个出栈就好

  还有一个共同点,都是科幻风格的,都是星际战争,通信都靠隧道,不知道出题人有没有借鉴的意思

  假装这篇博客是我刚写完星球大战这题时写的(其实是一年零两个月二十多天以后,写了zoj那题以后写的 2019年01月25日16:35:27)

[JSOI2008]星球大战

题目描述

  很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系。

  某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球。这些星球通过特殊的以太隧道互相直接或间接地连接。

  但好景不长,很快帝国又重新造出了他的超级武器。凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球。由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来。

  现在,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每一次打击之后反抗军占据的星球的连通块的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则这两个星球在同一个连通块中)。

输入输出格式

输入格式:

  输入文件第一行包含两个整数,$N (1<=N<=2M)$和$M (1<=M<=200,000)$,分别表示星球的数目和以太隧道的数目。星球用$ 0 ~ N−1 $的整数编号。

  接下来的 $M$ 行,每行包括两个整数 $X$, $Y$,其中($0<=X<>Y$ 表示星球 $x$ 和星球 $y$ 之间有 “以太” 隧道,可以直接通讯。

  接下来的一行为一个整数 $k$ ,表示将遭受攻击的星球的数目。

  接下来的 $k$ 行,每行有一个整数,按照顺序列出了帝国军的攻击目标。这 $k$ 个数互不相同,且都在 $0$ 到$n−1$的范围内。

输出格式:

  第一行是开始时星球的连通块个数。接下来的 $k$ 行,每行一个整数,表示经过该次打击后现存星球的连通块个数。

输入输出样例

输入样例#1: 复制

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
7
输出样例#1: 复制

1
1
1
2
3
3

说明

[JSOI2008]

源代码

 #include<stdio.h>//当年的一些中文注释的编码坏掉了

 int n,m,k;//n??μ?mì?±?k???Y?ù????

 int ruin[]={};
bool ru[]={};//ê?·?±??Y?ù
int num=;
int ans[]={},top=; struct Edge{
int next,to;
}e[];
int head[]={},cnt=;//40íò??μ?20íòì??T?ò±?
void add(int u,int v)
{
e[cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt++;
} int fa[];//?ó0?e£?2??ó1?e
int find(int x)
{
return fa[x]==x?x:(fa[x]=find(fa[x]));
}
inline bool uni(int x,int y)
{
x=find(x),y=find(y);
if(x==y) return false;
fa[x]=y;
return true;
} int main()
{
//freopen("test.txt","r",stdin);
for(int i=;i<;i++)
fa[i]=i; scanf("%d%d",&n,&m);
for(int i=,u,v;i<m;i++)
{
scanf("%d%d",&u,&v);
//printf("%d %d %d\n",cnt,u,v);
add(u,v);
//printf("%d %d %d\n\n",cnt,v,u);
add(v,u);
}
scanf("%d",&k);
for(int i=;i<k;i++)
scanf("%d",ruin+i),ru[ruin[i]]=true; num=;
for(int i=;i<n;i++)
{
if(!ru[i])
{
for(int j=head[i];j;j=e[j].next)
{
if(!ru[e[j].to])
uni(i,e[j].to);
}
}
}//í3??è?2??Y?ùoóμ?á?í?·?á?num
for(int i=;i<n;i++)
if(find(i)==i&&!ru[i]) num++;
ans[top++]=num;
//printf("^^^^\n");
for(int i=k-;i>=;i--)
{
ru[ruin[i]]=false;
int u=ruin[i];
int m=/*áùê±í3??áaí?·?á??eê§*/;
for(int j=head[u];j;j=e[j].next)
{
if(!ru[e[j].to])
if(uni(u,e[j].to))
{
m++;
//printf("%d %d ",u,e[j].to);
//printf("%d\n",j);
}
}
num-=m-;
ans[top++]=num;
}
top=k;
while(top>=)
{
printf("%d\n",ans[top]);
top--;
} return ;
}

星球大战

Connections in Galaxy War

Connections in Galaxy War


Time Limit: 3 Seconds      Memory Limit: 32768 KB

In order to strengthen the defense ability, many stars in galaxy allied together and built many bidirectional tunnels to exchange messages. However, when the Galaxy War began, some tunnels were destroyed by the monsters from another dimension. Then many problems were raised when some of the stars wanted to seek help from the others.

In the galaxy, the stars are numbered from 0 to N-1 and their power was marked by a non-negative integer pi. When the star A wanted to seek help, it would send the message to the star with the largest power which was connected with star A directly or indirectly. In addition, this star should be more powerful than the star A. If there were more than one star which had the same largest power, then the one with the smallest serial number was chosen. And therefore, sometimes star A couldn't find such star for help.

Given the information of the war and the queries about some particular stars, for each query, please find out whether this star could seek another star for help and which star should be chosen.

Input

There are no more than 20 cases. Process to the end of file.

For each cases, the first line contains an integer N (1 <= N <= 10000), which is the number of stars. The second line contains N integers p0p1, ... , pn-1 (0 <= pi <= 1000000000), representing the power of the i-th star. Then the third line is a single integer M (0 <= M <= 20000), that is the number of tunnels built before the war. Then M lines follows. Each line has two integers ab (0 <= ab <= N - 1, a != b), which means star a and star b has a connection tunnel. It's guaranteed that each connection will only be described once.

In the (M + 2)-th line is an integer Q (0 <= Q <= 50000) which is the number of the information and queries. In the following Q lines, each line will be written in one of next two formats.

"destroy a b" - the connection between star a and star b was destroyed by the monsters. It's guaranteed that the connection between star a and star b was available before the monsters' attack.

"query a" - star a wanted to know which star it should turn to for help

There is a blank line between consecutive cases.

Output

For each query in the input, if there is no star that star a can turn to for help, then output "-1"; otherwise, output the serial number of the chosen star.

Print a blank line between consecutive cases.

Sample Input

2
10 20
1
0 1
5
query 0
query 1
destroy 0 1
query 0
query 1

Sample Output

1
-1
-1
-1

Author: MO, Luyi
Source: ZOJ Monthly, November 2009

源代码

 #include<set>
#include<stdio.h>
#include<algorithm> int n,m=-,q; struct Opt{//o==d:a b; o==q: a;
char o;
int a;
int b;
int id;
bool operator < (const Opt & x)const{
return id>x.id;
}
}opt[]; struct Edge{
int s;
int t;
bool operator < (const Edge & x)const{
if(s==x.s) return t<x.t;
return s<x.s;
}
};
std::set<Edge> e;
std::set<Edge>::iterator it;
int ans[]; int p[],mx[],cnt[];
int fa[];
int find(int x)
{
if(fa[x]==x) return x;
fa[x]=find(fa[x]);
cnt[x]=cnt[fa[x]];
mx[x]=mx[fa[x]];
return fa[x];
}
void uni(int x,int y)
{
x=find(x);
y=find(y);
fa[x]=y;
cnt[y]+=cnt[x];
cnt[x]=cnt[y];
if(p[mx[x]]>p[mx[y]])
{
mx[y]=mx[x];
}
else if(p[mx[x]]==p[mx[y]])
{
mx[y]=mx[x]<mx[y]?mx[x]:mx[y];
}
mx[x]=mx[y];
} int main()
{
freopen("test.in","r",stdin);
while(~scanf("%d",&n))
{
if(m>=) printf("\n");
for(int i=;i<n;i++) mx[i]=fa[i]=i,cnt[i]=;
for(int i=;i<n;i++) scanf("%d",p+i);
scanf("%d",&m);
for(int i=,a,b;i<=m;i++)
{
scanf("%d%d",&a,&b);
e.insert({a,b});//查询时e.find({a,b})!=e.end()||e.find({b,a})!=e.end()
}
scanf("%d",&q);
for(int i=;i<=q;i++)
{
int a,b=;
char str[];
scanf("%s%d",str,&a);
if(str[]=='d')
{
scanf("%d",&b);
it=e.find({a,b});
if(it==e.end()) it=e.find({b,a});
e.erase(it);
}
opt[i]={str[],a,b,i};
}
std::sort(opt+,opt++q);
for(it=e.begin();it!=e.end();it++)
uni(it->s,it->t);
int num=;
for(int i=;i<=q;i++)
{
if(opt[i].o=='d')
{
uni(opt[i].a,opt[i].b);
}
else//q
{
find(opt[i].a);
if(p[mx[opt[i].a]]<=p[opt[i].a]) ans[num++]=-;
else ans[num++]=mx[opt[i].a];
}
} while(num>) printf("%d\n",ans[--num]); e.clear();
}
return ;
}

Connections in Galaxy War

洛谷 P1197 BZOJ 1015 [JSOI2008]星球大战 (ZOJ 3261 Connections in Galaxy War)的更多相关文章

  1. zoj 3261 Connections in Galaxy War

    点击打开链接zoj 3261 思路: 带权并查集 分析: 1 题目说的是有n个星球0~n-1,每个星球都有一个战斗值.n个星球之间有一些联系,并且n个星球之间会有互相伤害 2 根本没有思路的题,看了网 ...

  2. ZOJ 3261 Connections in Galaxy War(逆向并查集)

    参考链接: http://www.cppblog.com/yuan1028/archive/2011/02/13/139990.html http://blog.csdn.net/roney_win/ ...

  3. ZOJ 3261 - Connections in Galaxy War ,并查集删边

    In order to strengthen the defense ability, many stars in galaxy allied together and built many bidi ...

  4. ZOJ - 3261 Connections in Galaxy War(并查集删边)

    https://cn.vjudge.net/problem/ZOJ-3261 题意 银河系各大星球之间有不同的能量值, 并且他们之间互相有通道连接起来,可以用来传递信息,这样一旦有星球被怪兽攻击,便可 ...

  5. ZOJ 3261 Connections in Galaxy War (逆向+带权并查集)

    题意:有N个星球,每个星球有自己的武力值.星球之间有M条无向边,连通的两个点可以相互呼叫支援,前提是对方的武力值要大于自己.当武力值最大的伙伴有多个时,选择编号最小的.有Q次操作,destroy为切断 ...

  6. 题解报告:zoj 3261 Connections in Galaxy War(离线并查集)

    Description In order to strengthen the defense ability, many stars in galaxy allied together and bui ...

  7. zoj 3261 Connections in Galaxy War(并查集逆向加边)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3261 题意:有很多颗星球,各自有武力值,星球间有一些联系通道,现 ...

  8. BZOJ 1015: [JSOI2008]星球大战starwar 并查集

    1015: [JSOI2008]星球大战starwar Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝 ...

  9. BZOJ 1015 [JSOI2008]星球大战starwar

    1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 3551  Solved: 1581[Submit ...

随机推荐

  1. 蒟蒻的数位DP专题总结

    BZOJ  1026: [SCOI2009]windy数: 题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1026           d ...

  2. 20170322Linux

  3. luogu3084 Photo 单调队列优化DP

    题目大意 农夫约翰决定给站在一条线上的N(1 <= N <= 200,000)头奶牛制作一张全家福照片,N头奶牛编号1到N.于是约翰拍摄了M(1 <= M <= 100,000 ...

  4. mysql数据库操作(1)

    1.mysql 数据库备份: 语法: MYSQLDUMP -uUSER -pPASS DataBase > Path 其中:USER 是用户名,PASS 是密码,DataBase 是数据库名, ...

  5. EOJ 1641/UVa The SetStack Computer

    Background from Wikipedia: “Set theory is a branch of mathematics created principally by the German ...

  6. leetcode链表相关

    目录 2/445两数相加 综合题(328奇偶链表, 206反转链表, 21合并两个有序链表 ) 92反转链表 II 链表排序(148排序链表, 876链表的中间结点) 142环形链表 II 160相交 ...

  7. java 中接口的概念

    接口接口在java中是一个抽象的类型,是抽象方法的集合,接口通常使用interface来声明,一个类通过继承接口的方式从而继承接口的抽象方法.接口并不是类,编写接口的方式和类的很相似,但是他们属于不同 ...

  8. 【BZOJ1306】match循环赛

    预先警告:我的做法代码量比较大 看完题目后看到数据n<=8, 不难想到这题可以写深搜来做 分析 比如说以数据: 3 3 3 3 为例子, 进行了三场比赛:AB AC BC: 我们只要搜索每场比赛 ...

  9. POJ 2976 裸的01分数规划

    题意:给你n个数对(认为是a数组和b数组吧),从中取n-m个数对,如果选第i个数对,定义x[i]=1,求R=∑(a[i]*x[i])/∑(b[i]*x[i])取得最大值时R的值.输出R*100(保留到 ...

  10. xml之基本操作

    XML:Extensible Markup Language(可扩展标记语言)的缩写,是用来定义其它语言的一种元语言,其前身是SGML(Standard Generalized Markup Lang ...