[POI2004] SZP (贪心+拓扑排序)

Posted qihoo360

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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;
}

以上是关于[POI2004] SZP (贪心+拓扑排序)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ_2068_[Poi2004]SZP_树形DP

[bzoj3037/2068]创世纪[Poi2004]SZP_树形dp_并查集_基环树

BZOJ2067[Poi2004]SZN 二分+树上贪心

bzoj 2067 [Poi2004]SZN——二分+贪心

POI2004[MOS] 贪心+DP

[POI2014]RAJ(最短路,拓扑排序)