码迷,mamicode.com
首页 > 其他好文 > 详细

AtCoder Grand Contest 016 E - Poor Turkeys

时间:2018-12-24 12:06:06      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:cst   优化   nothing   rand   var   name   同时存在   getc   else   

题目传送门:https://agc016.contest.atcoder.jp/tasks/agc016_e

题目大意:

\(N\)只火鸡,现有\(M\)个人,每个人指定了两只火鸡\(x,y\),每人依次进行操作,会从\(x,y\)中选一只火鸡吃掉;如果只有一个,那么必定吃掉剩下那个;如果都没有,这个人只能饿着肚子离开了……

问最后有多少对火鸡可能存活

考虑倒序,我们设状态\(f_{i,j}\)表示如果要留下\(i\),那么是否要炖了\(j\),初始状态\(f_{i,i}=1\)

我们倒序考虑,如果\(f_{i,j}=1\),那么必然存在某个时刻会在\(i,j\)中抉择,这时\(j\)就会为了\(i\)挡枪子,但在这之前的时间,\(j\)需要收到和\(i\)一样的保护。那么这样就会牵扯到一堆火鸡,于是我们记\(S_i\)表示要留下\(i\),要为这一系列连锁反应挡枪的火鸡集合

如果存在某个时刻,需要在\(x,y\)中选择,但是存在\(f_{i,x}=f_{i,y}=1\),那么\(i\)就无法存活,这是结论1

考虑一对鸡\((i,j)\)如何被留下,如果存在一只鸡\(x\),既要保护\(i\),也要保护\(j\),那么\((i,j)\)必然不能共存,因为\(x\)只有一条命……因此我们可以得到,\((i,j)\)同时存在,当且仅当\(S_i\land S_j=\varnothing\),这是结论2

应用结论1和2即可,复杂度为\(O(nm+n^3)\),集合判交可以使用bitset优化

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
    static char buf[1000000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
    int x=0,f=1; char ch=gc();
    for (;ch<'0'||ch>'9';ch=gc())   if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<3)+(x<<1)+ch-'0';
    return x*f;
}
inline int read(){
    int x=0,f=1; char ch=getchar();
    for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())    x=(x<<3)+(x<<1)+ch-'0';
    return x*f;
}
inline void print(int x){
    if (x<0)    putchar('-'),x=-x;
    if (x>9)    print(x/10);
    putchar(x%10+'0');
}
const int N=4e2,M=1e5;
int A[M+10],B[M+10];
bool vis[N+10],sub[N+10][N+10];
int main(){
    int n=read(),m=read(),Ans=0;
    for (int i=1;i<=m;i++)  A[i]=read(),B[i]=read();
    for (int i=1;i<=n;i++){
        sub[i][i]=1;
        for (int j=m;j;j--){
            bool x=sub[i][A[j]],y=sub[i][B[j]];
            if (x&&y)   vis[i]=1;
            else    if (x)  sub[i][B[j]]=1;
            else    if (y)  sub[i][A[j]]=1;
        }
    }
    for (int i=1;i<=n;i++){
        if (vis[i]) continue;
        for (int j=i+1;j<=n;j++){
            if (vis[j]) continue;
            bool flag=1;
            for (int k=1;k<=n;k++)  if (sub[i][k]&&sub[j][k])   flag=0;
            Ans+=flag;
        }
    }
    printf("%d\n",Ans);
    return 0;
}

AtCoder Grand Contest 016 E - Poor Turkeys

标签:cst   优化   nothing   rand   var   name   同时存在   getc   else   

原文地址:https://www.cnblogs.com/Wolfycz/p/10167671.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!