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

  • 相关阅读:
    HDU 2544 最短路
    HDU 3367 Pseudoforest
    USACO 2001 OPEN
    HDU 3371 Connect the Cities
    HDU 1301 Jungle Roads
    HDU 1879 继续畅通工程
    HDU 1233 还是畅通工程
    HDU 1162 Eddy's picture
    HDU 5745 La Vie en rose
    HDU 5744 Keep On Movin
  • 原文地址:https://www.cnblogs.com/J-william/p/6414202.html
Copyright © 2011-2022 走看看