这个题开始很傻的以为求二分图匹配即可,但是后来发现是错的。这个题需要反向思考,记得最大独立集的话是说彼此之间没有边,在本题来说就是彼此之间不认识,那么我们如果对不认识的进行连边,然后找最大独立集,那么所求的就应该是最大互相认识的了。剩下的就简单了。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<queue> using namespace std; const int inf=1<<29; const int maxn=410; const int maxm=maxn*maxn; int e,st,des,head[maxn],pnt[maxm],nxt[maxm],flow[maxm],level[maxn]; int g,b,m; bool know[maxn][maxn]; queue<int> q; void AddEdge(int u,int v,int f) { pnt[e]=v;nxt[e]=head[u];flow[e]=f;head[u]=e++; pnt[e]=u;nxt[e]=head[v];flow[e]=0;head[v]=e++; } bool BFS() { memset(level,0,sizeof(level)); level[st]=1; q.push(st); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=nxt[i]) if(flow[i]&&!level[pnt[i]]) { level[pnt[i]]=level[u]+1; q.push(pnt[i]); } } return level[des]; } int DFS(int u,int maxf) { if(u==des||!maxf) return maxf; int f=0; for(int i=head[u];i!=-1;i=nxt[i]) if(flow[i]&&level[pnt[i]]==level[u]+1) { int t=DFS(pnt[i],min(flow[i],maxf-f)); if(t>0) { flow[i]-=t; flow[i^1]+=t; f+=t; if(f==maxf) break; } else level[pnt[i]]=0; } return f; } int maxflow() { int ans=0; while(BFS()) ans+=DFS(st,inf); return ans; } int main() { int cas=1; while(scanf("%d%d%d",&g,&b,&m)&&(g+b+m)) { memset(know,0,sizeof(know)); e=st=0;des=g+b+1; memset(head,-1,sizeof(head)); for(int i=0;i<m;i++) { int u,v; scanf("%d%d",&u,&v); know[u][v]=1; } for(int i=1;i<=g;i++) for(int j=1;j<=b;j++) if(!know[i][j]) AddEdge(i,g+j,1); for(int i=1;i<=g;i++) AddEdge(st,i,1); for(int i=1;i<=b;i++) AddEdge(g+i,des,1); printf("Case %d: %d\n",cas++,g+b-maxflow()); } return 0; }