• cogs1070玻璃球游戏


    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

    题目大意:每个点只有一个出度,给出每个点到达的点,如果是0说明这个点谁也不到达,给出一系列询问,问在某个点放玻璃球它能溜到哪个点,有环就输出有环,也有切断这个点的边。

    题解:并查集逆序处理

    切边不好切 可以倒着处理,怎么处理点在环上呢,当加边时,这个点到达的点的爸爸是当前这个点时,说明加上这个点就成环了,那么这个点到达的点的爸爸设为-1,这个点的爸爸为它到达的点,那么这个环里(别合并爸爸啊)的每一个点的祖先都是-1

    由于网的关系没有评测

    代码:

    #include<iostream>
    #include<cstdio>
    #define maxn 300002
    using namespace std;
    
    int n,m,cnt,ans[maxn],del[maxn],reach[maxn],fa[maxn];
    struct Q{
        int s,node;
    }query[maxn];
    
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    int f(int x){
        if(x==-1)return -1;return fa[x]==x?x:fa[x]=f(fa[x]);
    }
    
    int main(){
        freopen("marbles.in","r",stdin);
        freopen("marbles.out","w",stdout);
        n=read();
        for(int i=1;i<=n;i++)reach[i]=read(),fa[i]=i;
        m=read();
        for(int i=1;i<=m;i++){
            query[i].s=read();
            query[i].node=read();
            if(query[i].s==2)del[query[i].node]=1;    
        }
        for(int i=1;i<=n;i++){
            if(del[i]==0&&reach[i]){
                int v=f(reach[i]);
                if(v==i)fa[reach[i]]=-1;
                fa[i]=v;
            }
        }
        for(int i=m;i>=1;i--){
            if(query[i].s==1)ans[++cnt]=f(query[i].node);
            else{
                int ff=f(reach[query[i].node]);
                if(ff==query[i].node)fa[reach[query[i].node]]=-1;
                fa[query[i].node]=reach[query[i].node];
            //    cout<<"lala"<<" "<<query[i].node<<" "<<ff<<" "<<endl;
            }
        }
        //for(int i=1;i<=n;i++)cout<<fa[i]<<" ";
        for(int i=cnt;i>=1;i--){
            if(ans[i]==-1)printf("CIKLUS
    ");
            else 
            printf("%d
    ",ans[i]);
        }
        return 0;
    }

     

     

     

  • 相关阅读:
    re.sub函数的深入了解
    xpath
    改变评分查询
    Boolean Query
    固定分数查询
    Unicode编码的原型
    java中基本类型占用字节数
    Java Socket网络编程的经典例子(转)
    (转)工厂模式
    (转)java垃圾回收机制
  • 原文地址:https://www.cnblogs.com/zzyh/p/7444412.html
Copyright © 2020-2023  润新知