【优化】Problem 800: 可怜的火鸡

来源:互联网 发布:梯形螺纹加工编程 编辑:程序博客网 时间:2024/04/30 02:59

Problem 800: 可怜的火鸡
Time Limit: 1000 ms Memory Limit: 524288 KB 捆绑测试

Problem Description
有N只火鸡,有M次操作。每次操作的对象是Ai和Bi:

若Ai和Bi都还没被吃掉,选一只吃掉
若Ai和Bi都被吃掉了,则忽略这一次操作
若Ai和Bi只有一只还没被吃掉,则吃掉这一只
小J想知道在操作后有多少对(x,y)火鸡有可能还存活
N≤400,M≤10^5

【数据范围及子任务】

本题采用捆绑测试,你只有通过一个子任务的所有数据点才能获得该子任务的全部分数,否则该子任务得0分。

2≤N≤400

1≤M≤10^5

1≤xi

题解

dfs暴力40分

答案与边的顺序有关
我们反过来推
若[x,y]存在
则和 x或y 有关系的边 在[x,y]这条边前 必须存在 且不重复 而且没有交集
O(n^2)枚举边
O(m)逆序遍历
总时间O(n^2*m)

必须优化
考虑 对于每个点 每次将边加进一个集合中(若重复则不存在这个点)
枚举两个点判断是否有交集
加边O(n*m)
枚举交集O(n^2*n)
总时间O(n^3+n*m)

参考文献

[1]AtCoder Grand Contest 016做题记录
[2]cs的比赛总结

ac代码(可以把集合记录下来空间换时间,这里只用bool)

#include<cstdio>#include<iostream>#define N 410#define M 100010using namespace std;int n,m,u[M],v[M],ans;bool b[N][N],bo[N],boo;int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++){        scanf("%d%d",&u[i],&v[i]);    }    for(int i=1;i<=n;i++){        b[i][i]=1;        for(int j=m;j>=1;j--){            if(b[i][u[j]]&&b[i][v[j]]){                bo[i]=1;                break;            }            if(!b[i][u[j]]&&!b[i][v[j]])continue;            if(b[i][u[j]])b[i][v[j]]=1;            else b[i][u[j]]=1;        }    }    for(int i=1;i<=n;i++){        if(bo[i])continue;        for(int j=i+1;j<=n;j++){            if(bo[j]||b[i][j])continue;            boo=0;            for(int k=1;k<=n;k++)if(b[i][k]&&b[j][k]){                boo=1;                break;            }            if(!boo){//              printf("%d %d\n",i,j);                ans++;            }        }    }    printf("%d\n",ans);}

dfs(40分)

#include<cstdio>#include<iostream>#define M 100010#define N 410using namespace std;typedef long long LL;int num,n,m,u[M],v[M],a[N],ans;bool bo[N],b[N][N];inline int rd(){    char ch;    int p=0,q=1;    while((ch=getchar())<'0'||ch>'9')if(ch=='-')q=-1;    while(ch>='0'&&ch<='9')p=p*10+ch-'0',ch=getchar();    return p*q;}void dfs(int x){//  printf("%d\n",x);    if(x==m+1){        int cnt=0;        for(int i=1;i<=n;i++)if(!bo[i])a[++cnt]=i;//      for(int i=1;i<=n;i++)printf("%d ",bo[i]);//      printf("\n");//      printf("%d\n",cnt);        for(int i=1;i<=cnt;i++)            for(int j=1;j<=cnt;j++)                if(i!=j&&!b[a[i]][a[j]]){                    ans++;                    b[a[i]][a[j]]=b[a[j]][a[i]]=1;                }        return ;    }    if(bo[u[x]]&&bo[v[x]])dfs(x+1);    else if(bo[u[x]]){        bo[v[x]]=1;        dfs(x+1);        bo[v[x]]=0;    }    else if(bo[v[x]]){        bo[u[x]]=1;        dfs(x+1);        bo[u[x]]=0;    }    else {        bo[u[x]]=1;        dfs(x+1);        bo[u[x]]=0;        bo[v[x]]=1;        dfs(x+1);        bo[v[x]]=0;    }}int main(){    n=rd(); m=rd();    for(int i=1;i<=m;i++){        u[i]=rd();        v[i]=rd();    }    dfs(1);    printf("%d\n",ans);}
原创粉丝点击