二分图(二部图)
最大匹配 即 连接上下部分 边数和最大 的数量!
#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;
}