二分图的最大匹配:首先需要判断一个图是否为二分图,若是,才继续建模;
匈牙利算法,时间复杂度n*m;
poj1274 匈牙利算法模板题目;
/*poj1274二分图最大匹配,匈牙利算法,时间复杂度n*m*/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<climits>
#include<cctype>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<string>
#include<map>
#define ll long long
#define MAX 1000
#define eps 1e-8
#define INF INT_MAX
using namespace std;
vector<int>G[MAX];
int Left[MAX],n,m; //Left[i]记录二分图匹配中与右节点i相连的左节点,实际最终求得的匹配信息就记录在Left中
bool T[MAX];
bool match(int u){
for (int i = 0 ; i<G[u].size(); i++) if (!T[G[u][i]]){
int v = G[u][i];
T[v] = true;
if (!Left[v] || match(Left[v])){
Left[v] = u;
return true;
}
}
return false;
}
int KM(){
int cnt = 0;
memset(Left,0,sizeof(Left));
for (int i = 1; i<=n; i++){
memset(T,0,sizeof(T));
if (match(i)) cnt++; //cnt记录匹配数;
}
return cnt;
}
int main(){
while (scanf("%d%d",&n,&m) != EOF){
int c,t;
for (int i = 0; i<=n; i++) G[i].clear();
for (int i = 1; i<=n; i++){
scanf("%d",&c);
while (c--){
scanf("%d",&t);
G[i].push_back(t);
}
}
printf("%d\n",KM());
}
return 0;
}
网络流做法:建图,虚拟一个源点s,和一个汇点t,将原图中的左节点部分全部与s相连s->i,流量定为1;将原图中右节点部分全部与t相连i->t,流量也定位1;原图中已有的网络不变,流量为1。求一条从源点s到汇点t的最大流,即是匹配数,其中有流量的的边,即为匹配边;
poj1274网络流做法;
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<string>
#include<stack>
#include<set>
#define ll long long
#define MAX 1000
#define INF INT_MAX
#define eps 1e-8
using namespace std;
struct Edge{
int from,to,cap,flow;
};
vector<int>G[MAX];
vector<Edge>edges;
void init(){
for (int i=0; i<MAX; i++) G[i].clear();
edges.clear();
}
void addEdge(int from, int to, int cap){
edges.push_back((Edge){from,to,cap,0});
edges.push_back((Edge){to,from,0,0}); //添加反向边
int k = edges.size();
G[from].push_back(k-2);
G[to].push_back(k-1);
}
int d[MAX];
bool bfs(int s, int t){
bool vis[MAX];
queue<int>q;
memset(vis,false,sizeof(vis));
d[s] = 0;
q.push(s);
vis[s] = true;
while (!q.empty()){
int u = q.front();
q.pop();
for (int i=0; i<G[u].size(); i++){
Edge e = edges[G[u][i]];
if (!vis[e.to] && e.cap > e.flow){
vis[e.to] = true;
d[e.to] = d[u] + 1;
q.push(e.to);
}
}
}
return vis[t];
}
int cur[MAX];
int dfs(int s, int t, int a){
if (s == t || a == 0) return a;
int flow = 0, f;
for (int&i = cur[s]; i < G[s].size(); i++){
Edge& e = edges[G[s][i]];
if (d[s] + 1 == d[e.to] && (f = dfs(e.to,t,min(a,e.cap - e.flow))) > 0){
e.flow += f;
edges[G[s][i]^1].flow -= f;
flow += f;
a -= f;
if (a == 0) break;
}
}
return flow;
}
int Maxflow(int s, int t){ //s为源点,t为汇点的最大流
int flow = 0;
while (bfs(s,t)){
memset(cur,0,sizeof(cur));
flow += dfs(s,t,INF);
}
return flow;
}
int main(){
int n,m;
while (scanf("%d%d",&n,&m) != EOF){
init();
int s = 0, t = n+m+1;
int c,temp,u;
for (int i = 1; i<=n; i++){
addEdge(s,i,1);
scanf("%d",&c);
while (c--){
scanf("%d",&u);
addEdge(i,u+n,1);
}
}
for (int i = 1; i<=m; i++) addEdge(i+n,t,1);
printf("%d\n",Maxflow(s,t));
}
return 0;
}