poj 2771 有点难度最大独立集

来源:互联网 发布:淘宝运送方式怎么设置 编辑:程序博客网 时间:2024/06/05 14:55
题意:一个老师要带一些学生去旅游 , 下面任意两个学生至少要满足下面一个条件:
1、身高相差要超过40cm
2、性别相同
3、最喜欢的音乐属于不同类型
4、最喜欢的体育比赛相同

解 法:我们首先这样来考虑这个问题 , 以上4个条件 , 至少满足一个条件 , 因此对于满足有很多情况, 那么我们反过来想,如果所有条件都不满足 , 那么这个两个人肯定不能同时去 , 这中思想只需要一种情况 , 因此相对于正面解决简单很多,所以对于这中题目 , 我们往往从反面来做。

再 重新回到这个题目 , 如果两个人不能同时去 , 那么我们在这两个人之间连一条边 , 因此在我们所得到的图中,肯定是不存在环(环中至少存在两个点)的 , 因此一个人要么是男生, 要么是女生 , 由这样看 , 我们就能把这个图 ,变成一个二分图, 对于这个二分图 , 如果两个点之间存在直接的边相连 , 那么这两个人就只能去一个 , 再进一步思考 , 我们就能得到,只要求出这个的最大独立集 , 就是这个题目的答案

代码:
#include#include#include#include#includeusing namespace std;#define MAXN 510#define INF 1000000#define max(x , y) (x)>(y)?(x):(y)#define min(x , y) (x)<(y)?(x):(y)int n , m; //  记录每条边的权值int pre[MAXN] ;  // 记录和y中点匹配的点是哪个点vectorgrap[MAXN];int high[MAXN] ;char male[MAXN];char music[MAXN][111] , play[MAXN][111];int cx[MAXN] , cy[MAXN];void init(){    memset(pre ,0 , sizeof(pre));    for(int i =1; i <= n; i++)    {       grap[i].clear();    }    memset(cx ,-1 , sizeof(cx));    memset(cy ,-1 , sizeof(cy));}bool match(int i)  // 寻找增广路{     for(int j =0; j < grap[i].size(); j++)    {       int v = grap[i][j];       if(!pre[v])       {           pre[v] = 1;           if(cy[v] == -1 || match(cy[v]))           {               cx[i] = v;               cy[v] = i;               return true;           }       }       }    returnfalse;}int km(){    int i;       int res =0;    for(i = 1; i<= n; i++)    {       if(cx[i] == -1)       {           memset(pre , 0 , sizeof(pre));           if(match(i))  res += 1;       }       else res += 1;    }    returnres;}int main(){    int t;   cin>>t;   while(t--)    {       scanf("%d" , &n);       init();       int i , j , x , y , k = n;       for(i = 1; i <= n; i++)           scanf("%d %c %s %s" , &high[i] ,&male[i] , music[i] , play[i]);       n = 1, m = 1;       for(i = 1; i <= k; i++)//确定二分图           if(male[i] == 'M')  pre[i] = n++;           else pre[i] = m++;       for(i = 1; i <= k; i++)           for(j = i+1; j <= k; j++)           {               if(abs(high[i]-high[j]) > 40) continue;               if(male[i] == male[j])  continue;               if(strcmp(music[i],music[j]) != 0) continue;               if(strcmp(play[i] , play[j]) == 0) continue;                             x = pre[i] , y = pre[j];               if(male[i] == 'M')               {                   grap[x].push_back(y);                   if(cx[x] == -1 && cy[y] ==-1)                       cx[x] = y , cy[y] = x;               }               else               {                   grap[y].push_back(x);                   if(cx[y] == -1 && cy[x] ==-1)                       cx[y] = x , cy[x] = y;               }                         }             n -= 1;       x = km();             cout<<k-x<<endl;    }    return0;}


0 0
原创粉丝点击