zoukankan      html  css  js  c++  java
  • 对峙

    Problem 2 对峙(kill.cpp/c/pas)

    【题目描述】

    有n名杀手,每人持有一把枪并对准了某名杀手(可以是自己)。杀手被枪杀后就不能再开枪了。

    现在问你,在这种对峙情形下,被枪杀的杀手数量的最大值和最小值。开枪有严格的先后顺序,不存在同时开枪的情况。此外,不存在故意不开枪的情况,即每位杀手要么开枪,要么在开枪前被枪杀。

    【输入格式】

    第一行一个整数n,表示杀手人数。

    第二行n个整数,第i个数表示第i名杀手的枪对准的杀手,编号从1到n。

    【输出格式】

    一行两个整数,表示死亡的杀手数的最大值和最小值。注意本题有部分分,最大值和最小值各5分,如果你无法得出某个值,请在对应位置输入任意整数以保证格式正确。

    【样例输入】

    4

    2 3 1 1

    【样例输出】

    3 2

    【数据范围】

    对于30%的数据点,n <= 10;

    对于60%的数据点,n <= 1000;

    对于100%的数据点,n <= 100000。

    【题目分析】

        假设环的长度为len

        最大:在一个环中最多死掉len-1个人,在链中最多也是死掉环的长度-1个人,最后只剩下入度为0的点活着(想想活着多么美好啊)

        最小:入度为0的点指向的点一定会死,然后删除这个死掉的点,把这个点指向其他点的边和其他点指向这个点的边都删除,然后继续找下一个点,每一次都把入度为0的点入队。在环中最少会有len/2个人死掉

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=100010;
    int n,ans1,ans2,len,bo,h;
    int die[maxn],undie[maxn],q[maxn],a[maxn],In[maxn];
    
    int main()
    {
    //    freopen("kill.in","r",stdin);
    //    freopen("kill.out","w",stdout); 
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]),
            In[a[i]]++;
        for(int i=1;i<=n;i++)
            if(In[i]==0)
                ans1++,
                q[++ans2]=i;
        for(int i=1;i<=ans2;i++)
        {
            int k=a[q[i]];//k表示入度为0的点能杀死的人
            if(die[k]) continue;
            //如果k还没有被杀死 
            die[k]=1;undie[a[k]]=1;
            --In[a[k]];
            if(In[a[k]]==0) q[++ans2]=a[k];
        }
        for(int i=1;i<=n;i++)
            if(In[i]&&!die[i])
            {
                len=bo=0;
                for(int j=i;!die[j];j=a[j])//找每个点,保证这个点没有被杀,照完之后找他可以杀掉的
                    die[j]=1,//啊...死了 
                    len++,//环的长度 
                    bo+=undie[j];
                if(!bo&&len>1) //
                    ans1++;
                ans2+=len/2; //在环内活着的人最多len/2个 
            }
        printf("%d %d
    ",n-ans1,n-ans2);
    //    fclose(stdin);fclose(stdout);
        return 0; 
    }
  • 相关阅读:
    线程的补充
    线程
    进程
    操作系统和进程
    socketserver模块实现并发和连接合法性验证
    socketserver实例化过程
    粘包现象和解决方法
    网络通信协议
    初探网络
    Python网络编程
  • 原文地址:https://www.cnblogs.com/xiaoningmeng/p/5986071.html
Copyright © 2011-2022 走看看