[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 }