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;
}
posted @ 2018-07-16 09:49  水题收割者  阅读(177)  评论(0编辑  收藏  举报