[Poi2003 ]MAL猴子捞月

Time Limit:50000MS Memory Limit:65536K
Total Submit:18 Accepted:10
Case Time Limit:2000MS

Description

一棵树上有n 只猴子. 他们从1 到 n编号. 编号为1 的猴子用它的尾巴盘住了一个树枝. 剩下的猴子要么被其他的猴子钩住要么就是自己用手钩住其他的猴子. 每只猴子都可以用两只手去钩其他的猴子,每只手最多只能钩一只. 从0时刻开始, 每一秒都有一只猴子松开它的一只手. 这也许会造成一些猴子掉落到地上, 我们想要知道它们掉落地上的时间(猴子掉落的速度都非常的快,可以忽略掉落的时间).

Input

第一行包含两个整数n 和 m, 1 <= n <= 200000, 1 <= m <= 400000. 整数 n 代表猴子总数, 数 m 代表我们观察猴子的总时间. 接下来 n 行描述初始的情形. 第 (k + 1) 行 (1 <= k <= n) 有两个整数分别代表猴子k的左手和右手分别抓住了哪两只猴子. -1 代表它的那只手是空的. 接下来m 行代表我们观察到的猴子的活动. 第i行 有两个整数(1 <= i <= m) 代表在第i – 1时刻放开手的是哪只猴子和它放开的是哪只手(1 – 左, 2 – 右).

Output

输出n个整数每行一个代表每只猴子掉落到地上的时间, 如果没有掉落, 输出-1.

Sample Input

3 2
-1 3
3 -1
1 2
1 2
3 1

Sample Output

-1
1
1

Source

并查集

   考虑到这是一个连通性的问题,所以我们可以使用并查集。根据“手松开”这一特点,我们可以使用“时光倒流法”,按照时间顺序从后往前处理,将松开手转化为抓住,将分开两个集合转化为合并两个集合。
首先,离线处理出从始至终没有被删除的边,先将它们所连接的点合并。
然后,利用时光倒流法,若某一时刻松开手的两个猴子处在同一个集合中,那么就不用管他们;若他们处于不同的集合中,且其中一个集合中包含1,那么就把另一个集合所有点的掉落时间改为t,再把它们合并;若它们处于不同的集合中且每一个集合中都不包含1,那么就直接把它们合并。
那么,如何将集合中所有的点的掉落时间都改为t呢?可以用dfs实现。只需要在合并集合时连一条边就行了。
#include<algorithm>
#include<cstdio>
using namespace std;
int n,m,t=1,a[200010][3],s[400010][3],tt[200010];
int fa[200010],head[200010];
bool can[200010][3],vis[200010];
struct rec{  int nxt,data;
}node[2000010];  void add(int x,int y)
{node[t].data=y;node[t].nxt=head[x];head[x]=t;t++;  node[t].data=x;node[t].nxt=head[y];head[y]=t;t++;
}  int find(int x)
{  int tmp=x,pre;  while(tmp!=fa[tmp])tmp=fa[tmp];  while(x!=tmp){  pre=fa[x];  fa[x]=tmp;  x=pre;  }  return tmp;
}  void merge(int x,int y){  int fx=find(x),fy=find(y);  fa[fx]=fy;
}  void dfs(int now,int t)
{  vis[now]=true;  tt[now]=t;  for(int i=head[now];i;i=node[i].nxt)  if(!vis[node[i].data])  dfs(node[i].data,t);  vis[now]=false;
}int main()
{  scanf("%d%d",&n,&m);  for(int i=1;i<=n;i++){scanf("%d%d",&a[i][1],&a[i][2]);fa[i]=i; }for(int i=1;i<=m;i++){  scanf("%d%d",&s[i][1],&s[i][2]);  can[s[i][1]][s[i][2]]=true;  }  for(int i=1;i<=n;i++){  if(!can[i][1]&&a[i][1]!=-1){merge(i,a[i][1]); add(i,a[i][1]);}  if(!can[i][2]&&a[i][2]!=-1){merge(i,a[i][2]); add(i,a[i][2]);}  }  for(int i=m;i>=1;i--){  int x=a[s[i][1]][s[i][2]],y=s[i][1];  int fx=find(x),fy=find(y);  if(fx==fy)continue;  if(fx==find(1)){  dfs(fy,i);  merge(fx,fy);  add(x,y);  }  else if(fy==find(1)){  dfs(fx,i);  merge(fx,fy);  add(x,y);  }  else{  merge(fx,fy);  add(x,y);  }  }for(int i=1;i<=n;i++)  printf("%d\n",tt[i]-1);  return 0;
}

[Poi2003 ][bzoj 2601]MAL猴子捞月相关推荐

  1. BZOJ.1558.[JSOI2009]等差数列(线段树 差分)

    BZOJ 洛谷 首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做. 这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B ...

  2. S-T平面图中利用最短路求最小割(BZOJ 1001)

    BZOJ 1001: [BeiJing2006]狼抓兔子 最小割 题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 现在小朋友们最喜欢 ...

  3. BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)

    题意 有 \(n\) 个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪. 因此,对于不同的开枪顺序,最后死的人也不同. 问最 ...

  4. BZOJ 2957楼房重建

    传送门 线段树 //Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include< ...

  5. BZOJ.5249.[九省联考2018]iiidx(贪心 线段树)

    BZOJ LOJ 洛谷 \(d_i\)不同就不用说了,建出树来\(DFS\)一遍. 对于\(d_i\)不同的情况: Solution 1: xxy tql! 考虑如何把这些数依次填到树里. 首先对于已 ...

  6. bzoj 4871: [Shoi2017]摧毁“树状图”

    4871: [Shoi2017]摧毁"树状图" Time Limit: 25 Sec  Memory Limit: 512 MB Submit: 53  Solved: 9 [Su ...

  7. BZOJ 1592. Making the Grade(思维,数据结构优化DP,以及三个拓展问题)[Usaco2008 Feb]【BZOJ计划】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 BZOJ简单题合集x 目录 BZOJ 1592. Making the Grade 拓展问题一 拓展问 ...

  8. BZOJ 1590.Secret Message 秘密信息(Trie树) [Usaco2008 Dec]【BZOJ计划】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 BZOJ简单题合集x Weblink https://hydro.ac/d/bzoj/p/1590 P ...

  9. BZOJ 1589 Trick or Treat on the Farm (tarjan缩点,记忆化搜索)[Usaco 2008 Dec Gold]【BZOJ计划】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Weblink https://hydro.ac/d/bzoj/p/1589 Problem 每年万圣 ...

最新文章

  1. Route 66地图安装的一个简单方法,在N70上验证过
  2. 计算机林中鸟歌曲,励志歌曲曲-林中鸟
  3. android 点击网络图片大全,android查看网络图片的实现方法
  4. 20162321王彪 2017-2018-1 《程序设计与数据结构》第三周学习总结
  5. 前端趋势榜:上周最热门的 10 大前端项目 - 210327
  6. 排队器拦截_过滤器(Filter)和拦截器(Interceptor)的执行顺序和区别
  7. 剑指 Offer 44. 数字序列中某一位的数字
  8. php foreach id是否存在数组_请纠正这 5 个 PHP 编码小陋习
  9. kohana 简单使用
  10. Minimum Inversion Number 线段树
  11. 离职113天后,微软的“中国先生”沈向洋云受聘清华大学教授
  12. java对list里面按照分数排名_近3年全国高校高考录取分数线排名,600分以上高校55所...
  13. UNIX 与 WINDOWS 文本换行的差异
  14. 福大软工 · 第八次作业(课堂实战)- 项目UML设计(团队)
  15. 十个值得学习的c开源项目(嵌入式)
  16. 英国小黄车玩法,国际版抖音tiktok小店
  17. 周易八卦——数字卦预测的程序实现
  18. pyhton爬诛仙小说
  19. Javascript兼容IE8
  20. 使用showdoc快速生成在线文档

热门文章

  1. Linux之网络管理
  2. mysql left join和or_mysql – 在LEFT JOIN中使用带OR条件的索引
  3. 吴军推荐给中学生的书单
  4. php后台如何添加sitemap,织梦后台的sitemap生成及推送教程
  5. 关于C++、PHP和Swoole-韩天峰
  6. OC基础--对象做参数在方法间传递
  7. php 获取月份的周数,PHP获取当前月份的周数只能使用php
  8. 巧妙去掉多余的安全删除硬件图标
  9. Matlab:添加和删除表行
  10. thinkphp php5.1,ThinkPHP5.1完全开发手册