题目地址:http://poj.org/problem?id=3692
看网络流看了三天,isap算法真是难以理解。。因为isap,三天没怎么刷题了。。手痒痒,,所以怒敲一二分匹配,顺便巩固一下。这题刚上来感觉不太对的样子。。以为两天不做就不会了。。又想了想。。只不过是需要把反建而已。将原本输入中不匹配的进行连边。然后求出最小顶点覆盖,最后用总点数减去最小顶点覆盖数就是题目中所求的最多人数。
代码如下:
#include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <map> #include <algorithm> using namespace std; int n, link[300], vis[300], head[300], cnt, mp[300][300], num, n0; struct node { int u, v; int next; }edge[41000]; void add(int u, int v) { edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++; } int dfs(int u) { int i, v; for(i=head[u];i!=-1;i=edge[i].next) { v=edge[i].v; if(!vis[v]) { vis[v]=1; if(link[v]==-1||dfs(link[v])) { link[v]=u; return 1; } } } return 0; } void hungary() { int i, ans=0; memset(link,-1,sizeof(link)); for(i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if(dfs(i)) ans++; } printf("Case %d: %d\n",num,n+n0-ans); } int main() { int m, i, a, b, j; num=0; while(scanf("%d%d%d",&n,&n0,&m)!=EOF&&n&&n0&&m) { num++; memset(head,-1,sizeof(head)); cnt=0; memset(mp,0,sizeof(mp)); while(m--) { scanf("%d%d",&a,&b); mp[a][b]=1; } for(i=1;i<=n;i++) { for(j=1;j<=n0;j++) { if(!mp[i][j]) { add(i,j); } } } hungary(); } return 0; }