[agc016e]poor turkeys
题意:
有n只鸡,开始都活着。要按时间吃m次鸡,每次选两只,若两只都活着则随便吃一个,若只有一只活着就吃活的那个,如果死光了就不吃。问最后可能有多少对鸡同时存活(不考虑顺序)
$2\leq n\leq 400$
$1\leq m\leq 10^5$
题解:
妙啊思博题。考虑一直鸡$x$,如果要活下来那么在最后一次二选一的时候另外一只鸡也要活着,倒数第二次的时候另外那只鸡也要活着……即按照时间倒过来,另外的一些鸡必须要活着,$x$才能活下来,设这些必须活下来的鸡为$x$的存活集合。那么两只鸡同时存活下来的条件就是当且仅当两只鸡都有可能存活且相互之间的存活集合没有交集,否则必定有一只被吃。
直接暴力维护存活集合,时间复杂度$O(n^3+nm)$,不知道为什么跑的飞快
代码:
1 #include<iostream>
2 #include<cstring>
3 #include<cstdio>
4 #include<cmath>
5 using namespace std;
6 int n,m,ans=0,a[100001],b[100001];
7 bool ok[1001],st[1001][1001];
8 int main(){
9 scanf("%d%d",&n,&m);
10 for(int i=1;i<=m;i++){
11 scanf("%d%d",&a[i],&b[i]);
12 }
13 for(int i=1;i<=n;i++){
14 st[i][i]=1;
15 for(int j=m;j;j--){
16 int x=st[i][a[j]],y=st[i][b[j]];
17 if(x&&y){
18 ok[i]=true;
19 break;
20 }else{
21 if(x)st[i][b[j]]=1;
22 if(y)st[i][a[j]]=1;
23 }
24 }
25 }
26 for(int i=1;i<n;i++){
27 if(ok[i])continue;
28 for(int j=i+1;j<=n;j++){
29 if(ok[j])continue;
30 int tmp=1;
31 for(int k=1;k<=n;k++){
32 if(st[i][k]&&st[j][k]){
33 tmp=0;
34 break;
35 }
36 }
37 ans+=tmp;
38 }
39 }
40 printf("%d",ans);
41 return 0;
42 }