Damn Couples ZOJ - 3161
题目大意
N个人,M组关系,每次选一种关系,如果两个人相邻,则任意删除其中一个,否则不变。问最坏情况下最多能剩多少人。
分析
为了留的人最多,我们可以先将原来不相邻的关系全部说完,这样我们只需要考虑以怎样的顺序说剩下的那些即可。由于剩下的关系可能被分成一段一段的,所以我们只需要预处理在一个均相连的区间内有k个人最坏情况最多剩下多少人即可。经过考虑我们发现从中间将这一组关系分成两段可以使结果最优,所以我们就得到了递推式子,详见代码。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define sp cout<<"---------------------------------------------------"<<endl;
int id[1100],cnt;
struct node {
int x,y;
}d[1100];
inline bool cmp(const node a,const node b){
return a.x<b.x;
}
int main(){
int n,m,i,j,k=1,x,y;
id[1]=0,id[2]=1,id[3]=2,id[4]=2;
for(i=5;i<=500;i++)
if(i%2)id[i]=id[(i-1)/2-1]+id[(i-1)/2+1]+1;
else id[i]=id[i/2-1]+id[i/2]+1;
while(scanf("%d%d",&n,&m)!=EOF){
cnt=0;
for(i=1;i<=m;i++){
scanf("%d%d",&x,&y);
if(y<x)swap(x,y);
if(y-x!=1)continue;
d[++cnt].x=x,d[cnt].y=y;
}
sort(d+1,d+cnt+1,cmp);
int ans=n,len=1;
d[0].y=d[1].x;
for(i=1;i<=cnt;i++){
if(d[i].x!=d[i-1].y)ans-=id[len],len=2;
else len++;
}
ans-=id[len];
cout<<ans<<endl;
}
return 0;
}