花了一下午的时间看了匈牙利算法,大概弄懂了点,就是寻找增广路径,然后不断的更新路径。
用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; }