2043. 猴子

★★   输入文件:monkeya.in   输出文件:monkeya.out   简单对比
时间限制:1 s   内存限制:256 MB

【题目描述】

有n只猴子,第一只尾巴挂在树上,剩下的n-1只,要么被其他的猴子抓住,要么抓住了其他的猴子,要么两者均有。当然一只猴子最多抓两只另外的猴子,因为只有两只猴爪子嘛。现在给出这n只猴子抓与被抓的信息,并且在某个时刻可能某只猴子会放掉它左手或右手的猴子,导致某些猴子落在地上。求每只猴子落地的时间。

【输入格式】

第一行两个n,m,表示有n只猴子,并且总时间为m-1.

接下来n行,描述了每只猴子的信息,每行两个数,分别表示这只猴子左手和右手抓的猴子的编号,如果是-1,表示该猴子的那只手没抓其他的猴子。

再接下来M行,按时间顺序给出了一些猴子放手的信息,第1+n+i行表示i-1时刻某只猴子的放手信息,信息以两个数给出,前者表示放手的猴子的编号,后者表示其放的是哪只手,1左2右。

【输出格式】

共输出n行,第i行表示第i只猴子掉落的时刻,若第i只猴子道M-1时刻以后还没掉落,就输出-1。

【样例输入】

3 2

-1 3

3 -1

1 2

1 2

3 1

【样例输出】

-1

1

1

【提示】

n<=200000,m<=400000

【来源】

在此键入。

思路:

  逆向并查集~;

  这个题仔细读读可以发现这群猴子不按套路抓尾巴;

  可能一只猴子的尾巴会被很多只猴子抓;

  所以,这个题就成为了一个判断每个时间点连通性的问题;

  判断图的联通性自然是用并查集呀;

  但是,,,这个题貌似直接搞并查集不可行;

  所以,,要加一点点乱搞的操作;

  逆向并查集;

  我们读入每个猴子的左右手抓的尾巴(建图);

  然后,开始放手(删边);

  放手的同时,把放手的操作记录下来;

  然后,开始从第m-1秒到第0秒把放手的边加回去;

  没加一条边就通过并查集判断一下图的联通性;

  当当前块与1号联通时,就记录time;

  怎么记录time呢?略略恶心,,就不讲了,,可以去看看我的代码(直白如话);

  最后输出;

  轻松ac;

来,上代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> #define maxn 200005 using namespace std; struct NodeType {
int l,r; bool li,ri;
};
struct NodeType node[maxn<<]; struct EdgeType {
int to,next;
};
struct EdgeType edge[maxn<<]; int if_z,n,m,f[maxn],head[maxn],Time[maxn];
int cnt,do_s[maxn<<],do_w[maxn<<]; char Cget; bool if_[maxn],did[maxn]; inline void read_int(int &now)
{
now=,if_z=,Cget=getchar();
while(Cget>''||Cget<'')
{
if(Cget=='-') if_z=-;
Cget=getchar();
}
while(Cget>=''&&Cget<='')
{
now=now*+Cget-'';
Cget=getchar();
}
now*=if_z;
} inline void edge_add(int from,int to)
{
cnt++;
edge[cnt].to=to;
edge[cnt].next=head[from];
head[from]=cnt;
} int find(int x)
{
if(x==f[x]) return x;
f[x]=find(f[x]);
return f[x];
} void search(int now)
{
did[now]=true;
if(node[now].l!=-&&node[now].li)
{
int x=find(now),y=find(node[now].l);
if(x>y) swap(x,y);
if(x!=)
{
edge_add(x,y);
edge_add(y,x);
}
f[y]=x;
if(!did[node[now].l]) search(node[now].l);
}
if(node[now].r!=-&&node[now].ri)
{
int x=find(now),y=find(node[now].r);
if(x>y) swap(x,y);
if(x!=)
{
edge_add(x,y);
edge_add(y,x);
}
f[y]=x;
if(!did[node[now].r]) search(node[now].r);
}
} void search_(int now,int time_)
{
if_[now]=true;
Time[now]=time_;
for(int i=head[now];i;i=edge[i].next)
{
if(!if_[edge[i].to]) search_(edge[i].to,time_);
}
} int main()
{
freopen("monkeya.in","r",stdin);
freopen("monkeya.out","w",stdout);
memset(Time,-,sizeof(Time));
read_int(n),read_int(m);
m--;
for(int i=;i<=n;i++)
{
f[i]=i;
read_int(node[i].l);
read_int(node[i].r);
if(node[i].l!=-) node[i].li=true;
if(node[i].r!=-) node[i].ri=true;
}
for(int i=;i<=m;i++)
{
read_int(do_s[i]),read_int(do_w[i]);
if(do_w[i]==) node[do_s[i]].li=false;
else node[do_s[i]].ri=false;
}
for(int i=;i<=n;i++)
{
if(!did[i]) search(i);
}
for(int i=m;i>=;i--)
{
int x=do_s[i],y,x_,y_;
if(do_w[i]==) y=node[do_s[i]].l;
else y=node[do_s[i]].r;
if(y==-) continue;
x_=find(x),y_=find(y);
if(x_>y_) swap(x_,y_);
if(x_!=&&y_!=)
{
edge_add(x_,y_);
edge_add(y_,x_);
}
else if(x_!=&&y_==) Time[x_]=i;
else if(x_==&&y_!=) Time[y_]=i;
f[y_]=x_;
}
for(int i=;i<=n;i++)
{
if(Time[i]>=) search_(i,Time[i]);
}
for(int i=;i<=n;i++)
{
if(Time[i]<) printf("-1\n");
else printf("%d\n",Time[i]);
}
fclose(stdin);
fclose(stdout);
return ;
}

AC日记——猴子 cogs 2043的更多相关文章

  1. AC日记——codevs1688求逆序对

    AC日记--codevs1688求逆序对 锵炬 掭约芴巷 枷锤霍蚣 蟠道初盛 到被他尽情地踩在脚下蹂躏心中就无比的兴奋他是怎么都 ㄥ|囿楣 定要将他剁成肉泥.挫骨扬灰跟随着戴爷这么多年刁梅生 圃鳋 ...

  2. 洛谷 P1653 == COGS 2043 猴子

    P2107 可爱的猴子 时间限制:1000MS  空间限制:65535KB 问题描述: 树上有n只猴子.它们编号为 1 到n.1 号猴子用它的尾巴勾着树枝.剩下的猴子都被其他的猴子用手抓着.每只猴子的 ...

  3. AC日记——[NOIP2015]运输计划 cogs 2109

    [NOIP2015] 运输计划 思路: 树剖+二分: 代码: #include <cstdio> #include <cstring> #include <iostrea ...

  4. AC日记——[WC2013]糖果公园 cogs 1817

    [WC2013]糖果公园 思路: 带修改树上莫队(模板): 来,上代码: #include <cmath> #include <cstdio> #include <cst ...

  5. AC日记——[国家集训队2011]旅游(宋方睿) cogs 1867

    [国家集训队2011]旅游(宋方睿) 思路: 树链剖分,边权转点权: 线段树维护三个东西,sum,max,min: 当一个区间变成相反数时,sum=-sum,max=-min,min=-max: 来, ...

  6. AC日记——[国家集训队2010]小Z的袜子 cogs 1775

    [国家集训队2010]小Z的袜子 思路: 传说中的莫队算法(优雅的暴力): 莫队算法是一个离线的区间询问算法: 如果我们知道[l,r], 那么,我们就能O(1)的时间求出(l-1,r),(l+1,r) ...

  7. AC日记——[ZJOI2009]假期的宿舍 cogs 1333

    1333. [ZJOI2009] 假期的宿舍 ★★☆   输入文件:zjoi09holiday.in   输出文件:zjoi09holiday.out   简单对比时间限制:1 s   内存限制:25 ...

  8. AC日记——[福利]可持久化线段树 cogs 2554

    2554. [福利]可持久化线段树 ★★☆   输入文件:longterm_segtree.in   输出文件:longterm_segtree.out   简单对比时间限制:3 s   内存限制:2 ...

  9. AC日记——[网络流24题]骑士共存 cogs 746

    746. [网络流24题] 骑士共存 ★★☆   输入文件:knight.in   输出文件:knight.out   简单对比时间限制:1 s   内存限制:128 MB 骑士共存问题 «问题描述: ...

随机推荐

  1. MySQL中文转换成拼音的函数

    CREATE DEFINER=`root`@`localhost` FUNCTION `fristPinyin`(`P_NAME` VARCHAR(255) CHARSET utf8) RETURNS ...

  2. 【linux】【指令集】查看是否打开selinux

    > getenforce selinux相关原理资料参考 <鸟哥的linux私房菜>  http://cn.linux.vbird.org/linux_server/0210netw ...

  3. python 项目中包中__init__.py文件的作用

    开发python项目时,我遇到了一个这样的现象,当我新建一个pythonpackage时,总会自动地生成一个空的__init__.py文件,因为是python新手,所以很不了解这个空文件的作用是什么, ...

  4. 创建Django项目并将其部署在腾讯云上

    这段时间在做scrapy爬虫,对爬出来的数据基于Django做了统计与可视化,本想部署在腾讯云上玩玩,但是因为以前没有经验遇到了一些问题,在这里记录一下: 首先说下Django的创建与配置: 1. 创 ...

  5. LeetCode(122) Best Time to Buy and Sell Stock II

    题目 Say you have an array for which the ith element is the price of a given stock on day i. Design an ...

  6. LightOj:1422-Halloween Costumes

    传送门:http://www.lightoj.com/volume_showproblem.php?problem=1422 Halloween Costumes problem descriptio ...

  7. hdu 6318

    Long long ago, there was an integer sequence a.Tonyfang think this sequence is messy, so he will cou ...

  8. 打造一款属于自己的web服务器——从简单开始

    距离开篇已经过了很久,期间完善了一下之前的版本,目前已经能够完好运行,基本上该有的功能都有了,此外将原来的测试程序改为示例项目,新项目只需按照示例项目结构实现controller和view即可,详情见 ...

  9. CodeForces 14D 树的直径 Two Paths

    给出一棵树,找出两条不相交即没有公共点的路径,使得两个路径的长度的乘积最大. 思路:枚举树中的边,将该边去掉,分成两棵树,分别求出这两棵树的直径,乘起来维护一个最大值即可. #include < ...

  10. Selenium WebDriver-判断页面中某一元素是否已经显示,通常用于断言

    判断界面中某一元素是否已经呈现,多用于断言,代码如下: #encoding=utf-8 import unittest import time from selenium import webdriv ...