zoukankan      html  css  js  c++  java
  • 猴子

    ★★   输入文件: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

    思路:加权并查集||逆向并查集。

    代码实现:

     1 #include<cstdio>
     2 #include<iostream>
     3 #define maxn 200010
     4 #define maxm 400010
     5 using namespace std;
     6 int n,m;
     7 int s[2][maxn],f[maxn],ans[maxn];
     8 bool v[2][maxn];
     9 struct fame{int f,s;}e[maxm];
    10 int find(int x){
    11     if(f[x]==x) return x;
    12     int temp=find(f[x]);
    13     ans[x]=min(ans[x],ans[f[x]]);//权值操作。
    14     return f[x]=temp;
    15 }
    16 void get_fa(int x,int y,int z){//构造并查集。
    17     x=find(x),y=find(y);
    18     if(x!=y){
    19         if(x==1) f[y]=x,ans[y]=z;
    20         else f[x]=y,ans[x]=z;
    21     }
    22 }
    23 int main(){
    24     freopen("monkeya.in","r",stdin);
    25     freopen("monkeya.out","w",stdout);
    26     scanf("%d%d",&n,&m);
    27     for(int i=1;i<=n;i++){
    28         scanf("%d%d",&s[0][i],&s[1][i]);
    29         f[i]=i;ans[i]=maxm;//赋初值。
    30     }
    31     for(int i=1;i<=m;i++){
    32         scanf("%d%d",&e[i].f,&e[i].s);
    33         v[e[i].s-1][e[i].f]=1;
    34     }
    35     for(int i=1;i<=n;i++){//以点为关键正向构造。
    36         if(!v[0][i]&&s[0][i]!=-1) get_fa(i,s[0][i],m);
    37         if(!v[1][i]&&s[1][i]!=-1) get_fa(i,s[1][i],m);
    38     }
    39     for(int i=1;i<=n;i++) if(find(i)==1) ans[i]=maxm;//部分回归初值。
    40     for(int i=m;i>=1;i--) if(s[e[i].s-1][e[i].f]!=-1) get_fa(e[i].f,s[e[i].s-1][e[i].f],i-1);//以边为关键逆向构造。
    41     for(int i=1;i<=n;i++) find(i),printf("%d
    ",ans[i]==maxm?-1:ans[i]);
    42     return 0;
    43 }

    这道题还不太会。应该抽时间再练一下加权并查集。

    题目来源:COGS

  • 相关阅读:
    os
    linux常用命令
    css-基础知识
    awk命令详解
    文献综述
    微信JSAPI支付
    SNMP详解
    SNMP进阶
    SNMP协议入门
    SNMP简单网络管理协议
  • 原文地址:https://www.cnblogs.com/J-william/p/6414202.html
Copyright © 2011-2022 走看看