BZOJ 1124[POI2008]枪战
转载注明出处:http://www.cnblogs.com/radioteletscope/p/7276028.html
题面:
1124: [POI2008]枪战Maf
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 659 Solved: 259
[Submit][Status][Discuss]
Description
有n个人,每个人手里有一把手枪。一开始所有人都选定一个人瞄准(有可能瞄准自己)。然后他们按某个顺序开枪,且任意时刻只有一个人开枪。因此,对于不同的开枪顺序,最后死的人也不同。
Input
输入n人数<1000000 每个人的aim
Output
你要求最后死亡数目的最小和最大可能
Sample Input
8
2 3 2 2 6 7 8 5
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 }