首页 > 代码库 > BZOJ 1124[POI2008]枪战

BZOJ 1124[POI2008]枪战

题面:

1124: [POI2008]枪战Maf

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 659  Solved: 259
[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

最大值:n-(入度为零,aim不是自己的点)

最小值:入度为零的点一定不会死,它的aim一定会死,每次删去它和它的出边,再将入度为零的点加入。

如果出现环,则对答案的贡献为size/2

技术分享
 1 #include<stdio.h>
 2 using namespace std;
 3 #define maxn 1000001
 4 int q[maxn],a[maxn],IN[maxn],die[maxn],undie[maxn];
 5 int n;
 6 int ans1,ans2,len,bo;
 7 int main()
 8 {
 9     int x;
10     scanf("%d",&n);
11     for(int i=1;i<=n;i++)
12     {
13         scanf("%d",&a[i]);++IN[a[i]];
14     }
15     for(int i=1;i<=n;i++)
16         if(IN[i]==0)
17         {
18             ++ans1;q[++ans2]=i;
19         }
20     for(int i=1;i<=ans2;i++)
21     {
22         x=a[q[i]];
23         if(die[x])continue;
24         die[x]=1;
25         undie[a[x]]=1;--IN[a[x]];
26         if(IN[a[x]]==0)q[++ans2]=a[x];
27     }
28     for(int i=1;i<=n;i++)
29         if(IN[i]&&!die[i])
30         {
31             len=bo=0;
32             for(int j=i;!die[j];j=a[j])
33             {
34                 die[j]=1;
35                 ++len;
36                 bo|=undie[j];
37             }
38             if(!bo&&len>1)
39                 ++ans1;
40             ans2+=len/2;
41         }
42     printf("%d %d",n-ans2,n-ans1);
43 }
BZOJ 1124

 

BZOJ 1124[POI2008]枪战