bzoj 1124 [POI2008]枪战Maf 贪心

 [POI2008]枪战Maf

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 741  Solved: 295
[Submit][Status][Discuss]

Description

有n个人,每个人手里有一把手枪。一开始所有人都选定一个人瞄准(有可能瞄准自己)。然后他们按某个顺序开枪,且任意时刻只有一个人开枪。因此,对于不同的开枪顺序,最后死的人也不同。

Input

输入n人数<1000000 每个人的aim

Output

你要求最后死亡数目的最小和最大可能

Sample Input

8
2 3 2 2 6 7 8 5

Sample Output

3 5

HINT

 

 

 

  1 #include <queue>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6 #define N 1000100
  7 using namespace std;
  8 int n,cnt;
  9 int a[N];
 10 int du[N];
 11 int head[N];
 12 int vis[N];
 13 int v[N];
 14 int fir[N];
 15 struct node
 16 {
 17     int from,to,next;
 18 }edge[N<<1];
 19 int belong[N];
 20 int cnt_du[N];
 21 int siz[N];
 22 int tot;
 23 void init()
 24 {
 25     memset(head,-1,sizeof(head));
 26     cnt=1;
 27 }
 28 void edgeadd(int from,int to)
 29 {
 30     edge[cnt].from=from,edge[cnt].to=to,edge[cnt].next=head[from];
 31     head[from]=cnt++;
 32 }
 33 void dfs(int now,int ff)
 34 {
 35     vis[now]=1,belong[now]=tot,siz[tot]++;
 36     for(int i=head[now];i!=-1;i=edge[i].next)
 37     {
 38         int to=edge[i].to;
 39         if(to==now||to==ff||vis[to])continue;
 40         dfs(to,now);
 41     }
 42 }
 43 int check(int now,int num)
 44 {
 45     v[now]=1;
 46     int t=now,cntt=1;
 47     while(!v[a[t]])
 48     {
 49         v[a[t]]=1;
 50         t=a[t];
 51         cntt++;
 52     }
 53     t=a[t];
 54     if(t==now&&cntt==num)return 1;
 55     return 0;
 56 }
 57 int main()
 58 {
 59     init();
 60     scanf("%d",&n);
 61     for(int i=1;i<=n;i++)
 62     {
 63         scanf("%d",&a[i]);
 64         du[a[i]]++;
 65         edgeadd(i,a[i]);
 66         edgeadd(a[i],i);
 67     }
 68     for(int i=1;i<=n;i++)
 69     {
 70         if(!vis[i])
 71             tot++,dfs(i,0),fir[tot]=i;
 72     }
 73     for(int i=1;i<=n;i++)
 74     {
 75         if(du[i]==0)cnt_du[belong[i]]++;
 76     }
 77     int ansma=0,ansmi=0;
 78     for(int i=1;i<=tot;i++)
 79     {
 80         if(siz[i]==1)ansma++;
 81         if(check(fir[i],siz[i]))
 82             ansma+=siz[i]-1;
 83         else ansma+=siz[i]-cnt_du[i];
 84     }
 85     memset(v,0,sizeof(v));
 86     memset(vis,0,sizeof(vis));
 87     queue<int>q;
 88     for(int i=1;i<=n;i++)
 89     {
 90         if(!du[i])
 91             q.push(i);
 92     }
 93     while(!q.empty())
 94     {
 95         int u=q.front();
 96         q.pop();
 97         v[u]=1;
 98         if(!vis[a[u]])
 99         {
100             v[a[u]]=vis[a[u]]=1,ansmi++;
101             du[a[a[u]]]--;
102             if(!du[a[a[u]]])
103                 q.push(a[a[u]]);
104         }
105     }
106     for(int i=1;i<=n;i++)
107     {
108         if(!v[i])
109         {
110             int t=i,cnt=0;
111             while(!v[t])
112             {
113                 v[t]=1;
114                 cnt++;
115                 t=a[t];
116             }
117             ansmi+=(cnt+1)/2;
118         }
119     }
120     printf("%d %d\n",ansmi,ansma);
121 }

 

 

 

posted @ 2018-03-31 14:48  Kaiser-  阅读(303)  评论(0编辑  收藏  举报