• Cogs 1070. [焦作一中2012] 玻璃球游戏 带权并查集,逆序处理


    题目: http://cojs.tk/cogs/problem/problem.php?pid=1070

    1070. [焦作一中2012] 玻璃球游戏

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

    【问题描述】

    小x的业余生活中,有一项是玩滚玻璃球游戏。

    某天,小x想到了一种很无趣的玩法,当然,这种玩法就是为了玩看题的你们。

    小x首先建立了一个单向轨道,这个单向轨道可以抽象成一个有向图,每个顶点的出度都是1,也就是由每个点出发,只有一条边连向其他的点。

    小x的游戏最初规则是这样的:让玻璃球从某一个点出发,沿着有向边的方向,移动到它的下一个顶点,如果还能移动,就继续移动,直到没有相邻的边,当然会存在在一个环里不停运动的情况。

    为了增加难度,小x决定将游戏规则增强,他会提出一系列问题,让你回答:

    1) 格式:1 X.查询玻璃球由编号为X的点出发,最终在哪个点停下来,如果能停下来,输出最后的点的编号,如果停不下来,输出”CIKLUS”.

    2) 格式:2 X.删除由X出发的那条有向边。

    【输入】

    第一行包含一个正整数N(1<=N<=300000),表示图的顶点数。

    第二行包含由空格隔开N个正整数,第i个数表示从i顶点可以通过出边到达的定点编号,0表示该点没有出边。

    接下来的一行包含1个整数Q(1<=Q<=300000),表示询问的次数。

    再接下来Q行,每行表示一次查询,格式如题目描述。

    【输出】

    对于第1类询问,输出玻璃球停止时所在顶点编号,每行1个,按照查询的顺序输出。如果玻璃球无法停止,输出”CIKLUS”即可.

    【输入输出样例1】

    marbles.in

    marbles.out

    2 3 1 

    1 1 

    1 2 

    2 1 

    1 2 

    1 1 

    2 2 

    1 2

    CIKLUS 

    CIKLUS 

    2

    【输入输出样例2】

    marbles.in

    marbles.out

    0 3 5 3 4 

    1 1 

    1 2 

    2 4 

    1 2 

    2 3 

    1 2

    CIKLUS 

    3

    【数据范围】 

       40% 数据保证  N<=100,  Q<=1000

    题解:

    摘自liu_runda

    先处理完所有删边操作,再逆序处理所有操作(原来的删边处理时改为添边)。
    维护一个带权并查集(所谓的权就是会不会走到环路)。
    最后一个点用递归find()会爆栈,改迭代find()就可以了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define MAXN 300010
     4 #define MAXQ 300010
     5 int end[MAXN],fh[MAXQ],x[MAXQ],ans[MAXQ],father[MAXN];
     6 bool del[MAXN],circle[MAXN];
     7 int read()
     8 {
     9     int s=0,fh=1;char ch=getchar();
    10     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
    11     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
    12     return s*fh;
    13 }
    14 inline int Findfather(int o)
    15 {
    16     if(o==father[o])return father[o];
    17     else
    18     {
    19         father[o]=Findfather(father[o]);
    20         circle[o]=circle[father[o]];
    21         return father[o];
    22     }
    23 }
    24 inline void ak(int aa,int bb)
    25 {
    26     int a1=Findfather(aa);
    27     int b1=Findfather(bb);
    28     if(a1!=b1)father[a1]=b1;
    29     else
    30     {
    31         circle[a1]=true;circle[b1]=true;
    32     }
    33 }
    34 int main()
    35 {
    36     freopen("marbles.in","r",stdin);
    37     freopen("marbles.out","w",stdout);
    38     int i,N,Q,lans,xx;
    39     N=read();
    40     for(i=1;i<=N;i++)end[i]=read(),father[i]=i;
    41     Q=read();
    42     for(i=1;i<=Q;i++)
    43     {
    44         fh[i]=read();x[i]=read();
    45     }
    46     memset(del,false,sizeof(del));
    47     for(i=1;i<=Q;i++)
    48     {
    49         if(fh[i]==2)del[x[i]]=true;
    50     }
    51     memset(circle,false,sizeof(circle));
    52     for(i=1;i<=N;i++)
    53     {
    54         if(del[i]==false&&end[i]!=0)ak(i,end[i]);
    55     }
    56     lans=0;
    57     for(i=Q;i>=1;i--)
    58     {
    59         if(fh[i]==1)
    60         {
    61             xx=Findfather(x[i]);
    62             if(circle[x[i]]==true)ans[++lans]=-1;
    63             else ans[++lans]=Findfather(x[i]);
    64         }
    65         else
    66         {
    67             ak(x[i],end[x[i]]);
    68         }
    69     }
    70     for(i=lans;i>=1;i--)
    71     {
    72         if(ans[i]!=-1)printf("%d
    ",ans[i]);
    73         else printf("CIKLUS
    ");
    74     }
    75     fclose(stdin);
    76     fclose(stdout);
    77     return 0;
    78 }
    View Code
  • 相关阅读:
    I NEED A OFFER!
    水题 Codeforces Round #303 (Div. 2) A. Toy Cars
    模拟 HDOJ 5099 Comparison of Android versions
    模拟 HDOJ 5095 Linearization of the kernel functions in SVM
    贪心 HDOJ 5090 Game with Pearls
    Kruskal HDOJ 1863 畅通工程
    Kruskal HDOJ 1233 还是畅通工程
    并查集 HDOJ 1232 畅通工程
    DFS/并查集 Codeforces Round #286 (Div. 2) B
    水题 Codeforces Round #286 (Div. 2) A Mr. Kitayuta's Gift
  • 原文地址:https://www.cnblogs.com/Var123/p/5275671.html
Copyright © 2020-2023  润新知