zoukankan      html  css  js  c++  java
  • [POI2004] SZP (贪心+拓扑排序)

    【问题描述】
    Byteotian 中央情报局(BIA) 雇佣了许多特工. 他们每个人的工作就是监视
    另一名特工.
    Byteasar 国王需要进行一次秘密行动,所以他要挑选尽量多的信得过的特工. 但
    是这项任务是如此的机密以至于所有参加行动的特工都必须至少被另一名没有
    参加任务的特工所监视(就是说如果某个特工参加了行动,那么原先监视他的那些
    特工中至少要有一个没有参加进行动). 给出监视任务的详情,要求计算最多能有
    多少个特工参与其中.
    【输入格式】
    第一行只有一个整数, n – 特工的总数, 2 <= n <= 1000000. 特工从1 到n
    编号. 接下来n 行每行一个整数ak 表示特工k 将要监视特工ak , 1 <= k <= n, 1
    <= ak <= n, ak <> k.
    【输出格式】
    打印一个数,最多能有多少特工参加入这个任务.
    【样例输入】
    6
    2
    3
    l
    3
    6
    5
    【样例输出】
    3
    

    每个点的出度都为(1),很容易看出是基环外向树然而并没有用
    贪心+拓扑排序,如果一个点不选,则他的儿子一定要选。
    最后还剩下环,随便找个位置拆开就行了。

    #include <cstdio>
    #define Open(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);
    #define Close fclose(stdin);fclose(stdout);
    namespace IO{
        int xjc; char ch;
        inline int read(){
            xjc = 0; ch = getchar();
            while(ch < '0' || ch > '9') ch = getchar();
            while(ch >= '0' && ch <= '9'){ xjc = xjc * 10 + ch - '0'; ch = getchar(); }
            return xjc;
        }
    }using namespace IO;
    inline int min(int a, int b){
        return a > b ? b : a;
    }
    const int MAXN = 1000010;
    struct Queue{
        int s[MAXN];
        int head, tail;
        inline void push(int x){
            s[++tail] = x;
        }
        inline int pop(){
            return s[++head];
        }
        inline int size(){
            return tail - head;
        }
    }q;
    int n, a[MAXN], ans, vis[MAXN], in[MAXN];     //vis为1表示不选,为2表示选
    int main(){
        Open("szp");
        n = read();
        for(int i = 1; i <= n; ++i)
           ++in[a[i] = read()];
        for(int i = 1; i <= n; ++i)
           if(!in[i]) vis[i] = 1, q.push(i);
        while(q.size()){
          int now = q.pop();
          if(vis[now] == 1) vis[a[now]] = 2;
          if(!(--in[a[now]])){
            q.push(a[now]);
            if(!vis[a[now]]) vis[a[now]] = 1;
          }
        }
        for(int i = 1; i <= n; ++i){    //找剩下的环
           if(!vis[i]){
             int now = a[i], pos = i;
             while(now != i){
               if(vis[now]){
                 pos = now;
                 break;
               }
               now = a[now];
             }
             q.push(pos);
           }
        }
        while(q.size()){
          int now = q.pop();
          if(vis[now] == 1 && !vis[a[now]]) vis[a[now]] = 2;
          if(!(--in[a[now]])){
            q.push(a[now]);
            if(!vis[a[now]]) vis[a[now]] = 1;
          }
        }
        for(int i = 1; i <= n; ++i)
           if(vis[i] == 2) ++ans;
        printf("%d
    ", ans);
        return 0;
    }
    
    
  • 相关阅读:
    我渴望自由和成功(愿与君共勉)
    gdb使用 和core dump文件调试
    谷歌浏览器快捷键大全
    Android适屏
    BestCoder Round #33
    NAT&amp;Port Forwarding&amp;Port Triggering
    程序员应该学习的书
    java代码调用rtx发送提醒消息
    js实现excel导出
    一个跨界程序员:不务正业的这几年,我如何让自己的收入翻了十倍(转)
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/9822300.html
Copyright © 2011-2022 走看看