◆没有技术含量◆ eXam
◆最大匹配◆ The Perfect Stall
◆最小覆盖◆ Machine Schedule
其实本质是图论中的网络流
二分图是两个由多个点组成的集合(上部和下部,且没有重叠),两个集合中的点不与该集合内其他的点连通,但和另一个集合内的点连通。我们称这两个集合为上部、下部,或X、Y部,比如:
只要知道二分图的定义就可以了
/*Lucky_Glass*/
#include
#include
#include
#include
using namespace std;
int n_cla,n_stu,col[30005],error;
vector<int> vec[30005];
vector<int> ans;
void Solve(int u,int c)
{
col[u]=c;
if(c%2) ans.push_back(u);
for(int i=0;i<(int)vec[u].size();i++)
{
int v=vec[u][i];
if(col[v]){if((c+1)%2!=col[v]%2)error=true;continue;}
Solve(v,c+1);
if(error) return;
}
}
int main()
{
scanf("%d%d",&n_cla,&n_stu);
for(int i=1;i<=n_stu;i++)
{
int A,B;scanf("%d%d",&A,&B);
vec[B].push_back(A);vec[A].push_back(B);
}
for(int i=1;i<=n_cla;i++)
if(!col[i])
{
Solve(i,1);
if(error)
{
puts("no");
return 0;
}
}
printf("yes\n%d\n%d",ans.size(),ans[0]);
for(int i=1;i<(int)ans.size();i++)
printf(" %d",ans[i]);
return 0;
}
把匈牙利算法的板套上去
bool DFS(int u)
{
for(int i=0;i<(int)vec[u].size();i++) //枚举邻接点
{
int v=vec[u][i];
if(vis[v]) continue; //之前没有访问
vis[v]=true; //标记
if(mat[v]==0 || DFS(mat[v])) //如果该点没有匹配,或通过该点能向下找到一个未匹配点
{ //这就是一条增广路径
mat[u]=v;mat[v]=u; //反边
return true;
}
}
return false;
}
这道题比较基础,只要求找到最大匹配的数量,因此直接使用匈牙利算法,统计有多少组匹配就可以了。
- 源代码
/*Lucky_Glass*/
#include
#include
#include
#include
using namespace std;
#define MAXN 200
int n,m,mat[2*MAXN+5];
bool vis[2*MAXN+5];
vector<int> vec[2*MAXN+5];
bool DFS(int u)
{
for(int i=0;i<(int)vec[u].size();i++)
{
int v=vec[u][i];
if(vis[v]) continue;
vis[v]=true;
if(mat[v]==0 || DFS(mat[v]))
{
mat[u]=v;mat[v]=u;
return true;
}
}
return false;
}
int Solve()
{
int ans=0;
for(int i=1;i<=n;i++)
{
memset(vis,false,sizeof vis);
if(mat[i]==0 && DFS(i))
ans++;
}
return ans;
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
memset(mat,0,sizeof mat);
for(int i=1;i<=n;i++)
{
int n_;scanf("%d",&n_);
for(int j=0,x;jscanf("%d",&x);
vec[i].push_back(x+n);
vec[x+n].push_back(i);
}
}
printf("%d\n",Solve());
for(int i=1;i<=n;i++) vec[i].erase(vec[i].begin(),vec[i].end());
for(int i=1;i<=m;i++) vec[i+n].erase(vec[i+n].begin(),vec[i+n].end());
}
return 0;
}
就像一道结论题,结论一发现,就没什么难点了
/*Lucky_Glass*/
#include
#include
#include
#include
using namespace std;
#define MAXN 200
int n,m,mat[2*MAXN+5];
bool vis[2*MAXN+5];
vector<int> vec[2*MAXN+5];
bool DFS(int u)
{
for(int i=0;i<(int)vec[u].size();i++)
{
int v=vec[u][i];
if(vis[v]) continue;
vis[v]=true;
if(mat[v]==0 || DFS(mat[v]))
{
mat[u]=v;mat[v]=u;
return true;
}
}
return false;
}
int Solve()
{
int ans=0;
for(int i=1;i<=n;i++)
{
memset(vis,false,sizeof vis);
if(mat[i]==0 && DFS(i))
ans++;
}
return ans;
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
memset(mat,0,sizeof mat);
for(int i=1;i<=n;i++)
{
int n_;scanf("%d",&n_);
for(int j=0,x;jscanf("%d",&x);
vec[i].push_back(x+n);
vec[x+n].push_back(i);
}
}
printf("%d\n",Solve());
for(int i=1;i<=n;i++) vec[i].erase(vec[i].begin(),vec[i].end());
for(int i=1;i<=m;i++) vec[i+n].erase(vec[i+n].begin(),vec[i+n].end());
}
return 0;
}
− Lucky_Glass − L u c k y _ G l a s s