并查集--CSUOJ 1601 War
并查集的经典题目:
CSUOJ 1601: War
Time Limit: 1 Sec Memory Limit: 128 MB
Submit:
247 Solved: 70
[Submit][Status][Web
Board]
Description
AME decided to destroy CH’s country. In CH’ country, There are N villages,
which are numbered from 1 to N. We say two village A and B are connected, if and
only if there is a road between A and B, or there exists a village C such that
there is a road between A and C, and C and B are connected. To defend the
country from the attack of AME, CH has decided to build some roads between some
villages. Let us say that two villages belong to the same garrison area if they
are connected.
Now AME has already worked out the overall plan including
which road and in which order would be attacked and destroyed. CH wants to know
the number of garrison areas in his country after each of AME’s attack.
Input
The first line contains two integers N and M — the number of villages and
roads, (2 ≤ N ≤ 100000; 1 ≤ M ≤ 100000). Each of the next M lines contains two
different integers u, v (1<=u, v<=N)—which means there is a road between u
and v. The next line contains an integer Q which denotes the quantity of roads
AME wants to destroy (1 ≤ Q ≤ M). The last line contains a series of numbers
each of which denoting a road as its order of appearance — different integers
separated by spaces.
Output
Output Q integers — the number of garrison areas in CH’s country after each
of AME's attack. Each pair of numbers are separated by a single space.
Sample Input
3 1
1 2
1
1
4 4
1 2
2 3
1 3
3 4
3
2 4 3
Sample Output
3
1 2 3
/*题目大意:n个点m条边(边1,边2...边m),q个要摧毁的边,求按顺序每摧毁一条边后图中连通块的个数 题目分析:并查集,先找出最后状态,反向加边,先将q条路全部摧毁后的连通块个数求出来,然后加边即可,每加一条边,用并查集判断,若两点不在同一连通块中,则合并且连通块个数减1*/
#include<cstdio>
#include<cstring>
#define N 100100
struct Edge {
int u,v;
}edge[N];
bool visited[N];
int a[N],stack[N];
int n,m,q,ans=;
int father[N];
int find(int x)
{
return (father[x]==x)?father[x]:father[x]=find(father[x]);/*注意路径压缩和返回father[x]*/
}
void add_tu()
{
for(int i=;i<=n;++i)
father[i]=i;
for(int i=;i<=m;++i)
{
if(visited[i]) continue;
int r1=find(edge[i].u);
int r2=find(edge[i].v);
if(r1!=r2)
{
father[r2]=r1;
ans--;/*先把连通块的数目设为n,建图的过程中,边建边删除,也可以统计father[i]==i*/
}
}
stack[q]=ans;/*当前的状态是q的状态,不能加边了*/
}
void add_edge()
{
for(int i=q-;i>=;--i)
{
int r1=find(edge[a[i+]].u);/*注意加的这一条边是当前状态的后一条边,因为这个后一条边没有删除,而不是a[i],之前深受其害,连样例都过了*/
int r2=find(edge[a[i+]].v);
if(r1!=r2)
{
father[r2]=r1;
ans--; }
stack[i]=ans;/*注意不要把这句放到if里面*/
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)/*注意这里不能只用scanf("%d%d",&n,&m),因为这样没法用^z结束程序*/
memset(edge,,sizeof(edge));
memset(visited,false,sizeof(visited));/*别忘记初始化*/
memset(a,,sizeof(a));
memset(stack,,sizeof(stack));
ans=n;
for(int i=;i<=m;++i)
{
scanf("%d%d",&edge[i].u,&edge[i].v);
}
scanf("%d",&q);
for(int i=;i<=q;++i)
{
scanf("%d",&a[i]);
visited[a[i]]=true;/*把不访问的边设上标记*/
}
add_tu();
add_edge();
for(int i=;i<=q-;++i)
printf("%d ",stack[i]);/*CSUOJ这个坑爹的OJ,多输出一个空格,就格式不对*/
printf("%d\n",stack[q]);
}
return ;
}
并查集--CSUOJ 1601 War的更多相关文章
- ZOJ 3261 - Connections in Galaxy War ,并查集删边
In order to strengthen the defense ability, many stars in galaxy allied together and built many bidi ...
- Connections in Galaxy War (逆向并查集)题解
Connections in Galaxy War In order to strengthen the defense ability, many stars in galaxy allied to ...
- ZOJ3261:Connections in Galaxy War(逆向并查集)
Connections in Galaxy War Time Limit: 3 Seconds Memory Limit: 32768 KB 题目链接:http://acm.zju.edu. ...
- 题解报告:zoj 3261 Connections in Galaxy War(离线并查集)
Description In order to strengthen the defense ability, many stars in galaxy allied together and bui ...
- ZOJ3261 Connections in Galaxy War —— 反向并查集
题目链接:https://vjudge.net/problem/ZOJ-3261 In order to strengthen the defense ability, many stars in g ...
- 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 (逆向+带权并查集)
题意:有N个星球,每个星球有自己的武力值.星球之间有M条无向边,连通的两个点可以相互呼叫支援,前提是对方的武力值要大于自己.当武力值最大的伙伴有多个时,选择编号最小的.有Q次操作,destroy为切断 ...
- UVA 10158 War(并查集)
//思路详见课本 P 214 页 思路:直接用并查集,set [ k ] 存 k 的朋友所在集合的代表元素,set [ k + n ] 存 k 的敌人 所在集合的代表元素. #include< ...
- ZOJ-3261 Connections in Galaxy War 并查集 离线操作
题目链接:https://cn.vjudge.net/problem/ZOJ-3261 题意 有n个星星,之间有m条边 现一边询问与x星连通的最大星的编号,一边拆开一些边 思路 一开始是真不会,甚至想 ...
随机推荐
- eclipse运行Android项目出现“The connection to adb is down, and a severe error has occured. You must restart adb and Eclipse. ”
重启eclipse之后仍然出现同样错误,此时可以尝试一下方法: cmd打开命令窗口: 之后重启eclipse,基本可以解决问题!
- CF148A Insomnia cure
公主睡前数龙, 每隔k, l, m, n只都会用不同的技能攻击龙. 假定共数了d只龙, 问共有多少龙被攻击了. 思路: 用一个visit数组记录被攻击过的dragon, 最后遍历visit数组统计被攻 ...
- MSSQL 详解SQL Server连接(内连接、外连接、交叉连接)
在查询多个表时,我们经常会用“连接查询”.连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志. 什么是连接查询呢? 概念:根据两个表或多个表的列之间的关系,从这些表中查询数据 ...
- HDU 6197 array array array 2017沈阳网络赛 LIS
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6197 题意:给你n个数,问让你从中删掉k个数后(k<=n),是否能使剩下的序列为非递减或者非递增 ...
- 关于"轉淚點"与"轉捩點"
经常看台湾偶像剧或台湾综艺节目的人,一定听过"转泪点"这个词,虽然我一直不知道这三个字具体是怎么写, 但其意思很容易明白,就是"转折点"的意思.今天无聊在看凤凰 ...
- oracle中的符号含义
1.Oracle数据库存储过程中:=是什么意思?答:赋值的意思.举例:str := 'abcd';将字符串abcd赋值给变量str. 2.oracle 存储过程中的 := 和=有什么区别?答::= 是 ...
- 在Linux上安装pycharm
1.首先在官网下载pycharm并进行提取,将提取的文件夹放在/usr下面(或者任意位置) 2.然后vi /etc/hosts 编辑 将0.0.0.0 account.jetbrains.com添加到 ...
- ACM——【百练习题备忘录】
1. 在做百练2807题:两倍时,错将判断语句写成 a/b ==2,正确写法是:a == b*2 因为C/C++int型做除法时自动舍入,如:5/2 == 2,但是 5 =/= 2*2. 2. 在做百 ...
- Oracle常用sql语句(三)之子查询
子查询 子查询要解决的问题,不能一步求解 分为: 单行子查询 多行子查询 语法: SELECT select_list FROM table WHERE expr operator (SELECT s ...
- .Net Core 部署到 CentOS7 64 位系统中的步骤
建议使用 root 管理员账户操作 1.安装工具 1.apache 2..Net Core(dotnet-sdk-2.0) 3.Supervisor(进程管理工具,目的是服务器一开机就启动服务器 上发 ...