版权声明:转载注明下出处就行了。 https://blog.csdn.net/LJD201724114126/article/details/83962539
匈牙利算法参考链接:
https://blog.csdn.net/sixdaycoder/article/details/47680831
https://www.renfei.org/blog/bipartite-matching.html
题目一:
题意:
一共有N个学生跟P门课程,一个学生可以任意选一 门或多门课,问是否达成:
1.每个学生选的都是不同的课(即不能有两个学生选同一门课)
2.每门课都有一个代表(即P门课都被成功选过)
输入为:
第一行一个T代表T组数据
P N(P课程数, N学生数)
接着P行:
第几行代表第几门课程,首先是一个数字k代表对这门课程感兴趣的同学的个数,接下来是k个对这门课程感兴趣同学的编号。
题解:直接建个二分图搞定。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=310;
vector<int> G[maxn];
int match[maxn];
bool check[maxn];
bool dfs(int u)
{
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(!check[v]){
check[v]=true;
if(match[v]==-1||dfs(match[v])){
match[v]=u; ///学生匹配课程
return true;
}
}
}
return false;
}
int hungarian(int num_left)
{
int ans=0;
memset(match,-1,sizeof(match));
for(int u=0;u<num_left;u++)
{
memset(check,0,sizeof(check));
if(dfs(u)) ans++;
}
return ans;
}
int main()
{
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
int p,n;
scanf("%d%d",&p,&n);
for(int i=0;i<p;i++) ///课程
{
G[i].clear();
int counts,x;
scanf("%d",&counts);
while(counts--)
{
scanf("%d",&x);
G[i].push_back(x); ///课程i被学生x所喜欢
}
}
int ans=hungarian(p);
// printf("ans=%d\n",ans);
if(p-ans==0) puts("YES");
else puts("NO");
}
return 0;
}
题目二:
参考链接:https://blog.csdn.net/wchhlbt/article/details/76687002
https://www.2cto.com/kf/201308/233630.html
题意:见链接。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=51;
char op[maxn][maxn];
int x[maxn][maxn],y[maxn][maxn];
int maps[maxn*maxn][maxn*maxn];
bool vis[maxn*maxn];
int cx[maxn*maxn],cy[maxn*maxn];
int xpiece,ypiece;
int dfs(int u)
{
for(int v=1;v<=ypiece;v++)
{
if(maps[u][v]&&!vis[v]){
vis[v]=1;
if(cy[v]==-1||dfs(cy[v]))
{
cy[v]=u;
return 1;
}
}
}
return 0;
}
int hungarian()
{
memset(cy,-1,sizeof(cy));
int res=0;
for(int i=1;i<=xpiece;i++)
{
memset(vis,0,sizeof(vis));
res+=dfs(i);
}
return res;
}
int main()
{
int ncase;
scanf("%d",&ncase);
int T=0;
while(ncase--)
{
int m,n;
scanf("%d%d",&m,&n);
for(int i=0;i<m;i++)
scanf("%s",op[i]);
bool flag;
memset(x,0,sizeof(x)); ///初始化
memset(y,0,sizeof(y));
memset(maps,0,sizeof(maps));
xpiece=ypiece=0;
for(int i=0;i<m;i++) ///对横向分块
{
flag=true;
for(int j=0;j<n;j++){
if(op[i][j]=='o'){
if(flag)
x[i][j]=++xpiece,flag=false;
else x[i][j]=xpiece;
}
else if(op[i][j]=='#') flag=true;
}
}
for(int j=0;j<n;j++) ///对纵向分块
{
flag=true;
for(int i=0;i<m;i++){
if(op[i][j]=='o'){
if(flag) y[i][j]=++ypiece,flag=false;
else y[i][j]=ypiece;
}
else if(op[i][j]=='#') flag=true;
}
}
for(int i=0;i<m;i++) ///建图
{
for(int j=0;j<n;j++)
{
if(x[i][j]) {
maps[x[i][j]][y[i][j]]=1;
}
}
}
int sum=hungarian();
printf("Case :%d\n%d\n",++T,sum);
}
}