花了一下午的时间看了匈牙利算法,大概弄懂了点,就是寻找增广路径,然后不断的更新路径。
用dfs和bfs两种方法实现了下,注释详细。
dfs好写,容易懂,但是当点稀疏的时候效率没有bfs高。
bfs实现:
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
vector<int >a[510];
int ans;
int n,k;
void solve();
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&k);
for(int i=0;i<=n;i++)
a[i].clear();
for(int i=0;i<k;i++){
int x,y;
scanf("%d%d",&x,&y);
a[x].push_back(y);
}
ans = 0;
solve();
printf("%d\n",ans);
}
return 0;
}
//每一次在原有路径的基础上,找到一个未开发点,整体路径后移,使当前点插入(有多个路径)成为路径的开始
void solve(){
int visit[510]; //用值来记录哪个左点访问了优点
int matchleft[510]; //保存当前和左点i相连的右点
int matchright[510]; //保存当前和右点i相连的左点
int pre[510]; //保存当前路径左点的前一个点 无需初始化
memset(matchleft,0,sizeof(matchleft));
memset(matchright,0,sizeof(matchright));
memset(visit,0,sizeof(visit));
int flag; //标记每一次路径查找是否成功
for(int i=1;i<=n;i++){
if(a[i].size()>0&&matchleft[i]==0){
queue<int >q; //每查一个点重新申请,不用清零
q.push(i);
flag = 0;
pre[i] = 0; //标记
while(!q.empty()&&!flag){
int u = q.front();
q.pop(); //若已成功,则不必查找
for(int j=0;j<a[u].size()&&!flag;j++){
if(visit[a[u][j]]!=i){ //若右点a[u][j]没有被该点i访问(i是每一次的标志)
visit[a[u][j]] = i; //标记该点已经计算过
if(matchright[a[u][j]]!=0){ //若该右点已经有匹配,则与之匹配的左点进队列,尝试重新给这个左点匹配(有可能不可以重新匹配)
q.push(matchright[a[u][j]]);
pre[matchright[a[u][j]]] = u; //更新当前路径,u成为该路径中matchright[a[u][j]]点的前一个点
}
else{
flag = 1;
int x = u,y = a[u][j];
while(x!=0){ //回溯,直到到i
int t = matchleft[x]; //左右点的连线是由matchleft保存的
matchright[y] = x;
matchleft[x] = y;
y = t;
x = pre[x]; //路径是由pre保存的
}
}
}
}
}//两种办法计算结果都可以 ,但是flag跑的时间不稳定,原因未明
//if(flag) ans++;
}
if(matchleft[i]) ans++;
}
}
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<vector>
#include<list>
#include<algorithm>
using namespace std;
vector<int>a[510];
int book[510]; //girl
int visit[510]; //girl in every time
int dfs(int t);
int main(){
int T;
scanf("%d",&T);
while(T--){
int n,k;
scanf("%d%d",&n,&k);
for(int i=0;i<=n;i++){
a[i].clear();
}
for(int i=0;i<k;i++){
int x,y;
scanf("%d%d",&x,&y);
a[x].push_back(y);
}
memset(book,0,sizeof(book));
int ans = 0;
for(int i=0;i<=n;i++){
if(a[i].size()>0){
memset(visit,0,sizeof(visit));
if(dfs(i))
ans++;
}
}
printf("%d\n",ans);
}
return 0;
}
int dfs(int t){//find the girl
for(int i=0;i<a[t].size();i++){
if(visit[a[t][i]]==0){ //the girl is order by other man
visit[a[t][i]] = 1;
if(book[a[t][i]]==0||dfs(book[a[t][i]])){ //girl not have man or she can change
book[a[t][i]] = t;
return 1;
}
}
}
return 0;
}