二分图最大匹配 & 最大独立集

二分图(二部图)

最大匹配 即 连接上下部分 边数和最大 的数量!

#include <iostream> 
#include <string.h> 
using namespace std; 
int n,k;  //n矩阵规格,k星体数量 
int V1,V2;          //二分图顶点集 
 /*矩阵的行列分别属于二分图的两个顶点集V1、V2,其中行x∈V1,列y∈V2*/ 
bool grid[501][501];  //存储数据方式:可达矩阵 
bool vis[501];       //记录V2的点每个点是否已被搜索过 
int link[501];        //记录 V2中的点y 在 V1中 所匹配的点x的编号 
int m;  //最大匹配数 
bool dfs(int x) 
{ 
 for(int y=1;y<=V2;y++) 
    if(grid[x][y] && !vis[y])  //x到y相邻(有边) 且 节点y未被搜索 
  { 
      vis[y]=true;      //标记节点y已被搜索 
      if(link[y]==0 || dfs(link[y])) //link[y]==0 : 如果y不属于前一个匹配M 
      {              //find(link[y] : 如果被y匹配到的节点可以寻找到增广路 
        link[y]=x;   //那么可以更新匹配M'(用M替代M') 
    return true;  //返回匹配成功的标志 
   } 
  } 
  return false;  //继续查找V1下一个x的邻接节点 
} 
 
void search(void) 
{ 
 for(int x=1;x<=V1;x++) 
 { 
  memset(vis,false,sizeof(vis)); //清空上次搜索时的标记 
    if(dfs(x))  //从V1中的节点x开始寻找增广路 
   m++; 
 } 
 return; 
}

二分图最大匹配 hdu2063

//15MS	1248K	989 B
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 510
int g[MAX][MAX];
int K,M,N;
bool vis[MAX];
int link[MAX];
int m;
bool dfs(int src)
{
    for(int i=1;i<=N;i++)
    {
        if(g[src][i]&&!vis[i])
        {
            vis[i]=true;
            if(link[i]==0||dfs(link[i]))
            {
                link[i]=src;
                return true;
            }
        }
    }
    return false;
}
void search()
{
    memset(link,0,sizeof(link));
    for(int i=1;i<=M;i++)
    {
        memset(vis,false,sizeof(vis));
        if(dfs(i)) m++;
    }
}
int main()
{
    while(1)
    {
        scanf("%d",&K);
        if(!K) break;
        scanf("%d%d",&M,&N);
        m=0;
        memset(g,0,sizeof(g));
        for(int i=1;i<=K;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            g[x][y]=1;
        }
        search();
        printf("%d\n",m);
    }
    return 0;
}


最大独立集

=总权-最大匹配数

//448K	954MS	C++	1807B
#include <iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define clr(x) memset(x,0,sizeof(x))
int T;
int N;
int m;
struct People
{
    int heigh;
    char sex[5];
    char music[105];
    char sports[105];
}p[510];
struct Node
{
    int point;
    int next;
}node[200005];
int tot;
int head[510];
int vis[510];
int link[510];
bool cheak(People p1,People p2)
{
    if(abs(p1.heigh-p2.heigh)>40)
        return false;
    if(strcmp(p1.music,p2.music))
        return false;
    if(strcmp(p1.sports,p2.sports)==0)
        return false;
    return true;
}
void add(int x,int y) /*****邻接表*****/
{
    tot++;
    node[tot].next=head[x];
    node[tot].point=y;
    head[x]=tot;
}
bool dfs(int src)
{
    for(int e=head[src];e!=0;e=node[e].next)
    {
        if(!vis[node[e].point])
        {
            vis[node[e].point]=1;
            if(link[node[e].point]==0||dfs(link[node[e].point]))
            {
                link[node[e].point]=src;
                return true;
            }

        }
    }
    return false;
}
void search()
{
    for(int i=1;i<=N;i++)
    {
        clr(vis);
        if(p[i].sex[0]=='F'&&dfs(i))
            m++;
    }
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        /*********初始化*********/
        m=0;
        tot=0;
        //clr(node);
        clr(head);
        clr(link);

        scanf("%d",&N);
        for(int i=1;i<=N;i++)
        {
            scanf("%d%s%s%s",&p[i].heigh,p[i].sex,p[i].music,p[i].sports);
        }
        /******能做夫妻的就加为边******/
        for(int i=1;i<=N;i++)
            for(int j=1;j<=N;j++)
            if(p[i].sex[0]=='F'&&p[j].sex[0]=='M'&&cheak(p[i],p[j]))
            add(i,j);
            /**********求能做夫妻的最大匹配*************/
            search();
            /*********最大独立集=总权-最大匹配************/
            printf("%d\n",N-m);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值