效率较高:
#include <stack> #include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef struct node { int ord; node * next; }Node; const int size = 512+1; Node list[size]; int X[size]; int Y[size]; bool visit[size]; int size_x; int size_y; stack <int> stk; void init() { int i; for(i=1;i<=size;i++) list[i].next = NULL; memset(X,0,(size_x+1)*sizeof(int)); memset(Y,0,(size_y+1)*sizeof(int)); } void input(int len) { int i; int x; int y; Node *p; for(i=0;i<len;i++) { scanf("%d%d",&x,&y); p = new Node; p->ord=y; p->next = list[x].next; //邻接表存储 list[x].next=p; } } bool dfs(int x) { Node *p; stk.push(x); for(p=list[x].next;p;p=p->next) { if(!visit[p->ord]) { visit[p->ord] = true; stk.push(p->ord); if(!Y[p->ord] || dfs(Y[p->ord])) return true; else stk.pop(); } } stk.pop(); return false; } void solve() { int i ; int top; for(i=1;i<=size_x;i++) { while(!stk.empty()) stk.pop(); memset(visit,false,size_y+1); if(dfs(i)) { while(!stk.empty()) { top=stk.top(); stk.pop(); Y[top] = stk.top(); X[stk.top()] = top; stk.pop(); } } } } void output() { int i ; int count=0; Node * p; for(i=1;i<=size_x;i++) { if(X[i]) count++; while(p=list[i].next) { list[i].next=p->next; delete p; } } cout<<count<<endl; } int main() { int n ; while(scanf("%d",&n),n) { scanf("%d%d",&size_x,&size_y); init(); input(n); solve(); output(); while(!stk.empty()) stk.pop(); } return 0; }
帮助理解:
#include<iostream> #include<stdio.h> #include <memory.h> using namespace std; #define MAX 505 int map[MAX][MAX],flag[MAX]; int pre[MAX]; int n,m,num; int find(int cur) { int i; for(i=1;i<=m;i++)//m是男生的个数 { if(map[cur][i]&&!flag[i])//如果说这个男生和女生可以坐在一起而且这个男生在实验当中没有被任何女生占领 { flag[i]=1;//标记这个男生在实验当中被占领 if(pre[i]==-1||find(pre[i]))//如果这个男生没有被占领,或者通过增广路径,让拥有这个男生的女生找到啦新欢 { pre[i]=cur;//女生cur拥有这个男生 return 1;//因为找到,所以就这样做啦。返回1 } } } return 0;//这个女孩始终找不到增广路 } int main() { //freopen("in.txt","r",stdin); int i,girl,boy,sum; while(scanf("%d",&num),num) { //初始化 memset(map, 0, sizeof(map)); memset(pre, -1, sizeof(pre));sum = 0; //输入部分 scanf("%d %d",&n,&m); for(i = 0; i < num; i++) { scanf("%d %d", &girl, &boy); map[girl][boy] = 1; //可以匹配 } //开始匹配 for(i = 1; i <= n; i++) //女生去匹配男生 { memset(flag, 0, sizeof(flag)); //每次重新标记0 sum += find(i); } printf("%d\n", sum); } return 0; } /* 1 这个问题可以很容易的翻译一下:从第女生3查找的时候,发现男生1已经被女生2拥有啦,那么就让女生2去查找一个新的男生, 2 现在的问题是flag的就是标记每一次当中匹配和不匹配的男生。所以每一次都应该初始化 3 return 0表示,通过增广路径找不到新的。 */