zoukankan      html  css  js  c++  java
  • POJ 2771 最大点独立集

    这是经典的最大点独立集

    还是可以转化成最大匹配数,为什么呢,因为求出最大匹配数之和,匹配的边的两个端点互斥,只能去一个,所以最后结果就用总点数-最大匹配数即可

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int h[600],sex[600];
    char music[600][200],ball[600][200];
    int d[600][600],vis[600],lefts[600];
    int n;
    bool match(int u)
    {
        for (int v=0;v<n;v++){
            if (d[u][v] && !vis[v]){
                vis[v]=1;
                if (lefts[v]==-1 || match(lefts[v])){
                    lefts[v]=u;
                    return true;
                }
            }
        }
        return false;
    }
    int main()
    {
        int t;
        char tmp[3];
        scanf("%d",&t);
        while (t--)
        {
          scanf("%d",&n);
          for (int i=0;i<n;i++){
            scanf("%d%s%s%s",&h[i],tmp,music[i],ball[i]);
            if (tmp[0]=='M') sex[i]=1;
            else  sex[i]=0;
          }
          memset(d,0,sizeof d);
          for (int i=0;i<n;i++)
            for (int j=i+1;j<n;j++){
                if (abs(h[i]-h[j])<=40 && (sex[i]^sex[j]) && strcmp(music[i],music[j])==0 && strcmp(ball[i],ball[j])!=0){
                if (sex[i]==1) d[i][j]=1;
                else  d[j][i]=1;
              }
            }
          int sum=0;
          memset(lefts,-1,sizeof lefts);
          for (int i=0;i<n;i++){
            memset(vis,0,sizeof vis);
            if (match(i)) sum++;
          }
          int ans=n-sum;
          printf("%d
    ",ans);
        }
        return 0;
    }

    这个题目也可以不把男女生分开建图(上面我区分了男女,把男的放在左边) 全部统一建图,求出来的匹配数/2即可,原因很简单,其实就是统一建图就是把上面的图左右反过来又加在原图一下,所以匹配数是实际的两倍

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int h[600],sex[600];
    char music[600][20],ball[600][200];
    int d[600][600],vis[600],lefts[600];
    int n;
    bool match(int u)
    {
        for (int v=0;v<n;v++){
            if (d[u][v] && !vis[v]){
                vis[v]=1;
                if (lefts[v]==-1 || match(lefts[v])){
                    lefts[v]=u;
                    return true;
                }
            }
        }
        return false;
    }
    int main()
    {
        int t;
        char tmp[3];
        scanf("%d",&t);
        while (t--)
        {
          scanf("%d",&n);
          for (int i=0;i<n;i++){
            scanf("%d%s%s%s",&h[i],tmp,music[i],ball[i]);
            if (tmp[0]=='M') sex[i]=1;
            else  sex[i]=0;
          }
          memset(d,0,sizeof d);
          for (int i=0;i<n;i++)
            for (int j=i+1;j<n;j++){
                if (abs(h[i]-h[j])<=40 && (sex[i]^sex[j]) && strcmp(music[i],music[j])==0 && strcmp(ball[i],ball[j])!=0){
                d[i][j]=d[j][i]=1;
               // cout<<h[i]<<" "<<h[j]<<endl;
               // cout<<i<<" is connect "<<j<<endl;
              }
                else d[i][j]=d[j][i]=0;
            }
          int sum=0;
          memset(lefts,-1,sizeof lefts);
          for (int i=0;i<n;i++){
            memset(vis,0,sizeof vis);
            if (match(i)) sum++;
          }
          //cout<<sum<<endl;
          int ans=n-sum/2;
          printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    UpdateBatch到底是怎么用的?
    进度条在.net导入Excel时的应用实例
    asp.net页面触发事件panel滚动条高度不变的实现方法
    .NET中的枚举用法浅析
    .NET程序调试技巧(一):快速定位异常的一些方法
    ASP.NET实现推送文件到浏览器的方法
    微软官方SqlHelper类 数据库辅助操作类
    Asp.net中使用文本框的值动态生成控件的方法
    ASP.NET中Dictionary基本用法实例分析
    ASP.NET动态增加HTML元素的方法实例小结
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3768766.html
Copyright © 2011-2022 走看看