这道题和3081很像,,n+1----n+1+m 建立容量为k的边,如果map[i][j]==1 建立i---n+m+j容量为1的边 否则建i----n+j容量为1的边 然后二分具体见代码。。
还有一般数组适当开大,不要太大,会TLE...
#include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> #define MAXN 500 #define inf 0x3f3f3f3f #define MAXM 50000 using namespace std; struct node { int u,v,f; }; node e[MAXM]; int first[MAXN],next[MAXM]; int gap[MAXN],d[MAXN],curedge[MAXN],pre[MAXN]; int cc; int n,m,l,k; inline void add_edge(int u,int v,int f) { e[cc].u=u; e[cc].v=v; e[cc].f=f; next[cc]=first[u]; first[u]=cc; cc++; e[cc].u=v; e[cc].v=u; e[cc].f=0; next[cc]=first[v]; first[v]=cc; cc++; } int ISAP(int s,int t,int n) { int cur_flow,flow_ans=0,u,tmp,neck,i,v; memset(d,0,sizeof(d)); memset(gap,0,sizeof(gap)); memset(pre,-1,sizeof(pre)); for(i=0;i<=n;i++) curedge[i]=first[i]; gap[0]=n+1; u=s; while(d[s]<n+1) { if(u==t) { cur_flow=inf; for(i=s;i!=t;i=e[curedge[i]].v) { if(cur_flow>e[curedge[i]].f) { neck=i; cur_flow=e[curedge[i]].f; } } for(i=s;i!=t;i=e[curedge[i]].v) { tmp=curedge[i]; e[tmp].f-=cur_flow; e[tmp^1].f+=cur_flow; } flow_ans+=cur_flow; u=neck; } for(i=curedge[u];i!=-1;i=next[i]) { v=e[i].v; if(e[i].f&&d[u]==d[v]+1) break; } if(i!=-1) { curedge[u]=i; pre[v]=u; u=v; } else { if(0==--gap[d[u]]) break; curedge[u]=first[u]; for(tmp=n+5,i=first[u];i!=-1;i=next[i]) if(e[i].f) tmp=min(tmp,d[e[i].v]); d[u]=tmp+1; ++gap[d[u]]; if(u!=s) u=pre[u]; } } return flow_ans; } int map[100][100]; void build(int mid) { int i,j; memset(first,-1,sizeof(first)); memset(next,-1,sizeof(next)); memset(e,0,sizeof(e)); cc=0; for(i=1;i<=n;i++) add_edge(0,i,mid); for(i=n+1;i<=n+m;i++) add_edge(i,i+m,k); for(i=n+m+1;i<=n+m+m;i++) add_edge(i,n+m+m+1,mid); for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { if(map[i][j]) add_edge(i,n+m+j,1); else add_edge(i,n+j,1); } } } int main() { int tt; int cas; scanf("%d",&tt); for(cas=1;cas<=tt;cas++) { scanf("%d%d%d%d",&n,&m,&l,&k); int i; memset(map,0,sizeof(map)); for(i=0;i<l;i++) { int u,v; scanf("%d%d",&u,&v); map[u][v]=1; } int L=0,R=m,mid; int ans=0; while(L<=R) { mid=(L+R)/2; build(mid); int res=ISAP(0,n+m+m+1,n+m+m+1); //printf("%d\n",res); if(res==mid*n) { ans=mid; L=mid+1; } else R=mid-1; } printf("Case %d: %d\n",cas,ans); } return 0; }