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 100010
using 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 410
using 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);
}