洛谷 P1197 BZOJ 1015 [JSOI2008]星球大战 (ZOJ 3261 Connections in Galaxy War)
这两道题长得差不多,都有分裂集合的操作,都是先将所有操作离线,然后从最后一步开始倒着模拟,这样一来,分裂就变成合并,也就是从打击以后最终的零散状态,一步步合并,回到最开始所有星球都被连为一个整体的状态,这就能套并查集了。中途的询问结果用栈存下来,输出的时候一个个出栈就好
还有一个共同点,都是科幻风格的,都是星际战争,通信都靠隧道,不知道出题人有没有借鉴的意思
假装这篇博客是我刚写完星球大战这题时写的(其实是一年零两个月二十多天以后,写了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$ 行,每行一个整数,表示经过该次打击后现存星球的连通块个数。
输入输出样例
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
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 p0, p1, ... , 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 a, b (0 <= a, b <= 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)的更多相关文章
- zoj 3261 Connections in Galaxy War
点击打开链接zoj 3261 思路: 带权并查集 分析: 1 题目说的是有n个星球0~n-1,每个星球都有一个战斗值.n个星球之间有一些联系,并且n个星球之间会有互相伤害 2 根本没有思路的题,看了网 ...
- ZOJ 3261 Connections in Galaxy War(逆向并查集)
参考链接: http://www.cppblog.com/yuan1028/archive/2011/02/13/139990.html http://blog.csdn.net/roney_win/ ...
- ZOJ 3261 - Connections in Galaxy War ,并查集删边
In order to strengthen the defense ability, many stars in galaxy allied together and built many bidi ...
- ZOJ - 3261 Connections in Galaxy War(并查集删边)
https://cn.vjudge.net/problem/ZOJ-3261 题意 银河系各大星球之间有不同的能量值, 并且他们之间互相有通道连接起来,可以用来传递信息,这样一旦有星球被怪兽攻击,便可 ...
- ZOJ 3261 Connections in Galaxy War (逆向+带权并查集)
题意:有N个星球,每个星球有自己的武力值.星球之间有M条无向边,连通的两个点可以相互呼叫支援,前提是对方的武力值要大于自己.当武力值最大的伙伴有多个时,选择编号最小的.有Q次操作,destroy为切断 ...
- 题解报告:zoj 3261 Connections in Galaxy War(离线并查集)
Description In order to strengthen the defense ability, many stars in galaxy allied together and bui ...
- zoj 3261 Connections in Galaxy War(并查集逆向加边)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3261 题意:有很多颗星球,各自有武力值,星球间有一些联系通道,现 ...
- BZOJ 1015: [JSOI2008]星球大战starwar 并查集
1015: [JSOI2008]星球大战starwar Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝 ...
- BZOJ 1015 [JSOI2008]星球大战starwar
1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 3551 Solved: 1581[Submit ...
随机推荐
- Android将图像转换成流存储与将流转换成图像
1.将图片转换成二进制流 public byte[] getBitmapByte(Bitmap bitmap){ ByteArrayOutputStream out = new ByteArrayOu ...
- bzoj 4025 二分图 分治+并查集/LCT
bzoj 4025 二分图 [题目大意] 有n个点m条边,边会在start时刻出现在end时刻消失,求对于每一段时间,该图是不是一个二分图. 判断二分图的一个简单的方法:是否存在奇环 若存在奇环,就不 ...
- bzoj 1045 [HAOI2008] 糖果传递 —— 贪心
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1045 好像是贪心...但这是一个环... 看博客:http://hzwer.com/2656 ...
- PCB Genesis增加点阵字 实现原理
我们采用Genesis增加点阵字时,用Genesis增加Canned Text即可,但奥宝中文不支持,且字符种类是有限的呀 不过没关系,没有自己造呀.在这里我分享一种增加点阵字的实现方法 一.通过代码 ...
- PCB MS SQL 行转列
一.原数据: SELECT inman,indate FROM [fp_db].[dbo].[ppezhpbb] WHERE indate > '2016-5-1' AND indate < ...
- 图结构练习—BFSDFS—判断可达性(BFS)
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2138 注意该图为有向图,1000个点应该最多有 ...
- Speex回声消除原理深度解析
这里假设读者具有自适应滤波器的基础知识.Speex的AEC是以NLMS为基础,用MDF频域实现,最终推导出最优步长估计:残余回声与误差之比.最优步长等于残余回声方差与误差信号方差之比,这个结论可以记下 ...
- Java中final、finally、finalize的区别与用法
1.简单区别:final用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承.finally是异常处理语句结构的一部分,表示总是执行.finalize是Object类的一个方法,在垃 ...
- 使用T-sql建库建表建约束
为什么要使用sql语句建库建表? 现在假设这样一个场景,公司的项目经过测试没问题后需要在客户的实际环境中进行演示,那就需要对数据进行移植,现在问题来了:客户的数据库版本和公司开发阶段使用的数据库不兼容 ...
- 九九乘法表---for循环的嵌套
package com.zuoye.test;//控制台输出九九乘法表public class Jiujiu { public static void main(String[] args) { in ...