PAT天梯赛练习题 L2-013 红色警报(并查集+逆序加边)
L2-013. 红色警报
战争中保持各个城市间的连通性非常重要。本题要求你编写一个报警程序,当失去一个城市导致国家被分裂为多个无法连通的区域时,就发出红色警报。注意:若该国本来就不完全连通,是分裂的k个区域,而失去一个城市并不改变其他城市之间的连通性,则不要发出警报。
输入格式:
输入在第一行给出两个整数N(0 < N <=500)和M(<=5000),分别为城市个数(于是默认城市从0到N-1编号)和连接两城市的通路条数。随后M行,每行给出一条通路所连接的两个城市的编号,其间以1个空格分隔。在城市信息之后给出被攻占的信息,即一个正整数K和随后的K个被攻占的城市的编号。
注意:输入保证给出的被攻占的城市编号都是合法的且无重复,但并不保证给出的通路没有重复。
输出格式:
对每个被攻占的城市,如果它会改变整个国家的连通性,则输出“Red Alert: City k is lost!”,其中k是该城市的编号;否则只输出“City k is lost.”即可。如果该国失去了最后一个城市,则增加一行输出“Game Over.”。
输入样例:
5 4
0 1
1 3
3 0
0 4
5
1 2 0 4 3
输出样例:
City 1 is lost.
City 2 is lost.
Red Alert: City 0 is lost!
City 4 is lost.
City 3 is lost.
Game Over.
题目链接:PAT L2-013
跟NBUT火烧赤壁Ⅱ比较像,最后的连通分支数量计算错误导致第二组数据一直WA,草稿打N久才发现……
逆序加边就是先计算好初始(倒序)的结果,把所有没被攻占的边先拿去算一下连通分支数量, 然后再开始逆序加边,怎么加呢?就是把当前要加的点所连的边中选出另外一个点此时是也是未被攻占的这样一些边,然后拿去合并掉,显然有:连通分支数=前一次连通分支数+此时收复的领地数(就是1)-此时被成功合并的点。最后结果就当然要正序看,只有三种情况:1、连通分支数不变——攻占的是最外侧的点;2、连通分支数变多——攻占的点是至少连着两个点;3、连通分支数变少——攻占的点本身就是一个连通分支。
代码:
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<bitset>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define CLR(x,y) memset(x,y,sizeof(x))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=10000;
int pre[N],ran[N];
int vis[N];
vector<int>E[N];
pii edge[N];
vector<int>proces;
void init()
{
for (int i=0; i<N; ++i)
{
pre[i]=i;
ran[i]=1;
E[i].clear();
}
CLR(vis,0);
CLR(edge,0);
proces.clear();
}
int find(int n)
{
if(pre[n]!=n)
return pre[n]=find(pre[n]);
return n;
}
int joint(int a,int b)
{
int fa=find(a),fb=find(b);
if(fa!=fb)
{
if(ran[fa]>=ran[fb])
{
ran[fa]+=ran[fb];
pre[fb]=fa;
ran[fb]=0;
}
else
{
ran[fb]+=ran[fa];
pre[fa]=fb;
ran[fa]=0;
}
return 1;
}
return 0;
}
void partial_init()
{
for (int i=0; i<N; ++i)
{
pre[i]=i;
ran[i]=1;
}
}
int main(void)
{
int n,m,i,j,k,x,y;
while (~scanf("%d%d",&n,&m))
{
init();
for (i=0; i<m; ++i)
{
scanf("%d%d",&x,&y);
E[x].push_back(y);
E[y].push_back(x);
edge[i].first=x;
edge[i].second=y;
joint(x,y);
}
partial_init();
scanf("%d",&k);
vector<int>Q;
for (i=0; i<k; ++i)
{
scanf("%d",&x);
Q.push_back(x);
vis[x]=1;
}
int last=n-k;
for (i=0; i<m; ++i)//计算初始(倒序)连通分支数量
{
int x=edge[i].first;
int y=edge[i].second;
if(!vis[x]&&!vis[y])
last-=joint(x,y);
}
proces.push_back(last);
int SZ=Q.size();
for (i=SZ-1; i>=0; --i)
{
int now=Q[i];
vis[now]=0;
last++;
for (j=0; j<E[now].size(); ++j)
{
int v=E[now][j];
if(!vis[v])
{
if(joint(now,v))
--last;
}
}
proces.push_back(last);
}
int PZ=proces.size();
for (i=PZ-1; i>=1; --i)
{
if(proces[i]==proces[i-1]||proces[i]==proces[i-1]+1)
printf("City %d is lost.\n",Q[PZ-1-i]);
else
printf("Red Alert: City %d is lost!\n",Q[PZ-1-i]);
}
if(!proces[0])
puts("Game Over.");
}
return 0;
}
PAT天梯赛练习题 L2-013 红色警报(并查集+逆序加边)的更多相关文章
- 天梯赛决赛 L2-1.红色警报 并查集
L2-013. 红色警报 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 战争中保持各个城市间的连通性非常重要.本题要求你编写一 ...
- PAT天梯赛练习题——L3-007. 天梯地图(多边权SPFA)
L3-007. 天梯地图 时间限制 300 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 本题要求你实现一个天梯赛专属在线地图,队员输入自己学校 ...
- PAT天梯赛练习题——L3-004. 肿瘤诊断(三维连通块并查集)
L3-004. 肿瘤诊断 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 在诊断肿瘤疾病时,计算肿瘤体积是很重要的一环.给定病灶 ...
- PAT L2-013 红色警报(并查集求连通子图)
战争中保持各个城市间的连通性非常重要.本题要求你编写一个报警程序,当失去一个城市导致国家被分裂为多个无法连通的区域时,就发出红色警报.注意:若该国本来就不完全连通,是分裂的k个区域,而失去一个城市并不 ...
- L2-013. 红色警报 (并查集)
战争中保持各个城市间的连通性非常重要.本题要求你编写一个报警程序,当失去一个城市导致国家被分裂为多个无法连通的区域时,就发出红色警报.注意:若该国本来就不完全连通,是分裂的k个区域,而失去一个城市并不 ...
- L2-013. 红色警报(并查集+无向图联通分量)
战争中保持各个城市间的连通性非常重要.本题要求你编写一个报警程序,当失去一个城市导致国家被分裂为多个无法连通的区域时,就发出红色警报.注意:若该国本来就不完全连通,是分裂的k个区域,而失去一个城市并不 ...
- PAT天梯赛练习题 L3-002. 堆栈(线段树查询第K大值或主席树)
L3-002. 堆栈 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 大家都知道“堆栈”是一种“先进后出”的线性结构,基本操作有 ...
- PAT天梯赛练习题 L3-010. 是否完全二叉搜索树(完全二叉树的判断)
L3-010. 是否完全二叉搜索树 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 将一系列给定数字顺序插入一个初始为空的二叉搜 ...
- PAT天梯赛练习题 L3-011. 直捣黄龙(多关键字SPFA+DFS)
L3-011. 直捣黄龙 时间限制 150 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 本题是一部战争大片 —— 你需要从己方大本营出发,一路 ...
随机推荐
- Linux/Ubuntu下解压命令
.tar 解包:tar xvf FileName.tar 打包:tar cvf FileName.tar DirName (注:tar是打包,不是压缩!) ——————————————— .gz 解压 ...
- python基础——函数的参数
python基础——函数的参数 定义函数的时候,我们把参数的名字和位置确定下来,函数的接口定义就完成了.对于函数的调用者来说,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复 ...
- 如何用OpenCV自带的adaboost程序训练并检测目标
参考博文: 1.http://blog.csdn.net/wuxiaoyao12/article/details/39227189 2.http://www.cnblogs.com/easymind2 ...
- 安装phpredis模块
[root@web01 src]# wget github.com/owlient/phpredis/tarball/master [root@web01 src]# tar -xzvf master ...
- Nginx开启Gzip压缩大幅提高页面加载速度
[root@12 conf]# vi nginx.conf gzip on;#开启GZIP gzip_min_length 1k; #不压缩临界值,大于1K的才压缩,一般不用改 gzip_buffer ...
- hibernate的sqlQuery自动封装
1.Query query = session.createSQLQuery("SQL").addEntity(Tree.class); //返回对象 List list = ...
- 完美搞定《DOCKER IN ACTION》第二章示例
起来!!!命令如下: 建立第一个web docker docker run --detach --name web nginx:latest 建立第二个web_test docker docker r ...
- git merge 合并分支
git merge 用来做分支合并,将其他分支中的内容合并到当前分支中.比如分支结构如下: master / C0 ---- C1 ---- C2 ---- C4 \ C3 ---- C5 \ iss ...
- 翻阅《数据结构与算法javascript描述》--数组篇
导读: 这篇文章比较长,介绍了数组常见的操作方法以及一些注意事项,最后还有几道经典的练习题(面试题). 数组的定义: JavaScript 中的数组是一种特殊的对象,用来表示偏移量的索引是该对象的属性 ...
- AngularJS 'Controller As'用法
AngularJS 1.2版本中提供了Controller As语法,简单说就是可以在Controller中使用this来替代$scope,使得Controller更像一个传统的JS类,相对于$sco ...