给定一图求最小点覆盖。
最大二分匹配=最小点覆盖
bfs版匈牙利算法
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn = 1550;
struct edge
{
int from,to;
};
vector<int> g[maxn];
vector<edge> edges;
int n;
int check[maxn],match[maxn],pre[maxn];
void addedge(int from,int to)
{
edges.push_back(edge{from,to});
edges.push_back(edge{to,from});
int m=edges.size();
g[from].push_back(m-2);
g[to].push_back(m-1);
}
int Hungarian()
{
int ans=0;
memset(match,-1,sizeof(match));
memset(check,-1,sizeof(check));
for(int i=0;i<n;i++)
{
queue<int> q;
if(match[i]==-1)
{
q.push(i);
pre[i]=-1;
bool flag=false;
while(!q.empty()&&!flag)
{
int u=q.front();
for(int j=0;j<g[u].size()&&!flag;j++)
{
edge &e=edges[g[u][j]];
int v=e.to;
if(check[v]!=i)
{
check[v]=i;
q.push(match[v]);
if(match[v]>=0)pre[match[v]]=u;
else
{
flag=1;
int d=u,e=v;
while(d!=-1)
{
int t=match[d];
match[d]=e;
match[e]=d;
d=pre[d];
e=t;
}
}
}
}
q.pop();
}
if(match[i]!=-1)ans++;
}
}
return ans;
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
int u,num,v;
for(int i=0;i<=n;i++)g[i].clear();
edges.clear();
for(int i=0;i<n;i++)
{
scanf("%d:(%d)",&u,&num);
while(num--)
{
scanf("%d",&v);
addedge(u,v);
}
}
int ans=Hungarian();
printf("%d\n",ans);
}
}
dfs版本
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 1505;
struct edge
{
int from,to;
};
vector<edge> edges;
vector<int> g[maxn];
int check[maxn],match[maxn];
int n;
void addedge(int from,int to)
{
edges.push_back(edge{from,to});
edges.push_back(edge{to,from});
int m=edges.size();
g[from].push_back(m-2);
g[to].push_back(m-1);
}
bool dfs(int u)
{
for(int i=0;i<g[u].size();i++)
{
int v=edges[g[u][i]].to;
if(!check[v])
{
check[v]=1;
if(match[v]==-1||dfs(match[v]))
{
match[v]=u;
match[u]=v;
return true;
}
}
}
return false;
}
int Hungarian()
{
int ans=0;
memset(match,-1,sizeof(match));
for(int i=0;i<n;i++)
{
if(match[i]==-1)
{
memset(check,0,sizeof(check));
if(dfs(i))
++ans;
}
}
return ans;
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
int u,num,v;
edges.clear();
for(int i=0;i<n;i++)g[i].clear();
for(int i=0;i<n;i++)
{
scanf("%d:(%d)",&u,&num);
while(num--)
{
scanf("%d",&v);
addedge(u,v);
}
}
int ans;
ans=Hungarian();
printf("%d\n",ans);
}
}