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. 分割catalina.out 每天生成一个文件

    1. touch xxx(文件名字).sh 2.     vim xxx.sh 写入  ----------------------- #!/bin/sh cd `dirname $0`pwdd=`d ...

  2. DeepFaceLab小白入门(3):软件使用!

    换脸程序执行步骤,大部分程序都是类似.DeepFaceLab 虽然没有可视化界面,但是将整个过程分成了8个步骤,每个步骤只需点击BAT文件即可执行.只要看着序号,一个个点过去就可以了,这样的操作应该不 ...

  3. Python简单试题3

    1,水仙花数 水仙花数是指一个 3 位数,它的每个位上的数字的 3次幂之和等于它本身 (例如:1^3 + 5^3+ 3^3 = 153)  代码如下: 方法一: for i in range(100, ...

  4. MYSQL安装与库的基本操作

    mysql数据库 什么是数据库 # 用来存储数据的仓库 # 数据库可以在硬盘及内存中存储数据 数据库与文件存储数据区别 数据库本质也是通过文件来存储数据, 数据库的概念就是系统的管理存储数据的文件 数 ...

  5. iOS开发-NSLog不打印设置 Prefix

    首先在-Prefix.pch,文件里添加如下代码 #ifdef DEBUG #define NSLog(...) NSLog(__VA_ARGS__) #define debugMethod() NS ...

  6. 02_ThreadLocal语法与源码分析

    文章导读: 早在JDK 1.2的版本中就提供Java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程 ...

  7. Selenium WebDriver- 操作JavaScript的Alert弹窗

    弹层和弹框是有区别的,弹框是那种完全没样式的框子:弹层是可以直接看到html的,有样式 #encoding=utf-8 import unittest import time from seleniu ...

  8. Selenium WebDriver- 操作 IFrame 中的页面元素

    #encoding=utf-8 import unittest import time from selenium import webdriver from selenium.webdriver i ...

  9. python 学习分享-字典篇

    python字典(Dictionary) dict是无序的 key必须是唯一切不可变的 a={'key1':'value1','key2':'value2'} 字典的增删改查 a['key3']='v ...

  10. 九度oj 题目1456:胜利大逃亡

    题目描述: Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会.魔王住在一个城堡里,城堡是一个A*B*C的立方体,可以被表示成A个B*C的矩阵,刚开始Ignatius ...