[POI2008]枪战Maf

题目描述

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

输入

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

输出

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

样例输入

8
2 3 2 2 6 7 8 5

样例输出

3 5

solution:
  这个题调的让我想吐(太弱了QAQ),首先进行缩点,如果自杀min,max都加1,然后把它自己分一个点,如果是这个环点个数大于1切缩点后入度为0,min+=(num[i]+1)/2,max+=(num[i]-1),还要考虑环缩点后入度不为0的情况,把所有点进行排序,先按照这点是否需要被处理,把需要被处理的放后面,(前面两种情况均已经处理不用再被处理),然后再按照入度从小到大排序,for循环找到第一个入度不为0且需要被处理的点,记录下标为ji,break。max+=n-ji+1。
   最小死亡比较难求,要找到第一个入读为零且需要处理的点,再找到最后一个入度为0且需要被处理的点,(其实就是ji-1),把这之间的点压入队列,把队列中要杀的人全部杀掉,看这些被杀的人的要杀的人的入度是否变为0,如果为0且每死亡继续入队,没杀一个min++,最后输出即可。
  这题也可以树dp,但本蒟蒻没打出来,这题在cogs上交需要手动开大栈空间,否则会RE
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cstdlib>
  6 using namespace std;
  7 #define inf 0x7fffffff
  8 __attribute__((optimize("O3")))int read() {
  9     int s=0,f=1;
 10     char ch=getchar();
 11     while(ch>'9'||ch<'0') {
 12         if(ch=='-') {
 13             f=-1;
 14         }
 15         ch=getchar();
 16     }
 17     while(ch>='0'&&ch<='9') {
 18         s=(s<<1)+(s<<3)+(ch^48);
 19         ch=getchar();
 20     }
 21     return s*f;
 22 }
 23 int n,r[1000005],tot;
 24 struct node {
 25     int fr,to,next;
 26 } c[2000005];
 27 void add(int x,int y) {
 28     c[tot]=(node) {
 29         x,y,r[x]
 30     };
 31     r[x]=tot++;
 32 }
 33 int a[1000005],num[1000005],cnt,tim,dfn[1000005],low[1000005],p,belong[1000005],st[1000005];
 34 bool in[1000005];
 35 __attribute__((optimize("O3")))void tar(int x) {
 36     dfn[x]=low[x]=++tim;
 37     st[++p]=x;
 38     in[x]=1;
 39     for(int i=r[x]; ~i; i=c[i].next) {
 40         if(dfn[c[i].to]==-1) {
 41             tar(c[i].to);
 42             low[x]=min(low[x],low[c[i].to]);
 43         } else {
 44             if(in[c[i].to]) {
 45                 low[x]=min(low[x],dfn[c[i].to]);
 46             }
 47         }
 48     }
 49     if(dfn[x]==low[x]) {
 50         int y;
 51         ++cnt;
 52         do {
 53             y=st[p--];
 54             in[y]=0;
 55             num[cnt]++;
 56             belong[y]=cnt;
 57         } while(x!=y);
 58     }
 59 }
 60 int min_ans,max_ans,indexx[1000005];
 61 bool need_done[1000005],flag[1000005];
 62 struct oo {
 63     int ord;
 64 } point[1000005];// 1 chuliguo 0 meiyouchuli
 65 __attribute__((optimize("O3")))bool cmp(oo a,oo b) {
 66     if(need_done[belong[a.ord]]>need_done[belong[b.ord]]) {
 67         return 0;
 68     }
 69     if(need_done[belong[a.ord]]<need_done[belong[b.ord]]) {
 70         return 1;
 71     }
 72     if(indexx[a.ord]<indexx[b.ord]) {
 73         return 1;
 74     }
 75     return 0;
 76 }
 77 int queue[1000005],head,tail;
 78 bool die[1000005];
 79 __attribute__((optimize("O3")))int main() {
 80     //freopen("maf10.in","r",stdin);
 81     //freopen("maf.out","w",stdout);
 82     /*int __size__= 128 << 20;
 83     char *__p__ = (char*)malloc(__size__) + __size__;
 84     __asm__("movl %0, %%esp\n" :: "r"(__p__));
 85     */
 86     n=read();
 87     cnt=0;
 88     memset(r,-1,sizeof(r));
 89     memset(dfn,-1,sizeof(dfn));
 90     for(int x,i=1; i<=n; i++) {
 91         a[i]=x=read();
 92         point[i].ord=i;
 93         if(a[i]==i) {
 94             min_ans++;
 95             max_ans++;
 96             belong[i]=++cnt;
 97             num[cnt]=1;
 98             die[i]=1;
 99             need_done[cnt]=0;
100             continue;
101         }
102     }
103     for(int i=1;i<=n;i++){
104         int to=a[i];
105         if(!die[i]&&!die[to]){
106             indexx[to]++;
107             add(i,to);
108         }
109     }
110     for(int i=1; i<=n; i++) {
111         if(dfn[i]==-1&&!die[i]) {
112             tar(i);
113         }
114     }
115     for(int i=0; i<tot; i++) {
116         if(belong[c[i].fr]!=belong[c[i].to]) {
117             need_done[belong[c[i].fr]]=1;
118             need_done[belong[c[i].to]]=1;
119         }
120     }
121     for(int i=1; i<=cnt; i++) {
122         if(!need_done[i]&&num[i]>1) {
123             max_ans+=num[i]-1;
124             min_ans+=(num[i]+1)/2;
125         }
126     }
127     sort(point+1,point+n+1,cmp);
128     int ji=0;
129     for(int i=1; i<=n; i++) {
130         if(need_done[belong[point[i].ord]]&&indexx[point[i].ord]) {
131             ji=i;
132             break;
133         }
134     }
135     max_ans+=n-ji+1;
136     int pos1=inf;
137     for(int i=1; i<=n; i++) {
138         if(!indexx[point[i].ord]&&need_done[belong[point[i].ord]]) {
139             pos1=i;
140             break;
141         }
142     }
143     for(int i=pos1; i<ji; i++) {
144         queue[++tail]=point[i].ord;
145     }
146     while(head<tail) {
147         int h=queue[++head];
148         need_done[belong[h]]=0;
149         if(die[a[h]]) {
150             continue;
151         }
152         die[a[h]]=1;
153         min_ans++;
154         need_done[belong[a[h]]]=0;
155         indexx[a[a[h]]]--;
156         if(!indexx[a[a[h]]]&&!die[a[a[h]]]) {
157             need_done[belong[a[a[h]]]]=0;
158             queue[++tail]=a[a[h]];
159         }
160     }
161     for(int i=1; i<=cnt; i++) {
162         if(need_done[i]) {
163             min_ans+=(num[i]+1)/2;
164         }
165     }
166     printf("%d %d",min_ans,max_ans);
167     return 0;
168 }

 

 
posted @ 2017-08-03 07:28  Forever_goodboy  阅读(215)  评论(1编辑  收藏  举报