poj 3189 Steady Cow Assignment 枚举+网络流
枚举区间建图,好像也可以用多重匹配来做,不过不是很熟
新建源点向每头牛连边
牛向barns连边
barns向汇点连边,边权为barns的容量,其实就是一个二分图
最后求最大流就好了
View Code
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAX=100005; const int INF=1000000000; struct { int v,c,next; }edge[1000000]; int E,head[MAX]; int gap[MAX],cur[MAX]; int pre[MAX],dis[MAX]; void add_edge(int s,int t,int c,int cc) { /*加边的时候同时加两条, 一条正的,一条反的, 一般情况下反的容量是0 */ edge[E].v=t; edge[E].c=c; edge[E].next=head[s]; head[s]=E++; edge[E].v=s; edge[E].c=cc; edge[E].next=head[t]; head[t]=E++; } int min(int a,int b){return (a==-1||b<a)?b:a;} int SAP(int s,int t,int n) { memset(gap,0,sizeof(gap)); memset(dis,0,sizeof(dis)); int i; for(i=0;i<n;i++)cur[i]=head[i]; int u=pre[s]=s,maxflow=0,aug=-1,v; gap[0]=n; while(dis[s]<n) { loop: for(i=cur[u];i!=-1;i=edge[i].next) { v=edge[i].v; if(edge[i].c>0&&dis[u]==dis[v]+1) { aug=min(aug,edge[i].c); pre[v]=u; cur[u]=i; u=v; if(u==t) { for(u=pre[u];v!=s;v=u,u=pre[u]) { edge[cur[u]].c-=aug; edge[cur[u]^1].c+=aug; } maxflow+=aug; aug=-1; } goto loop; } } int mindis=n; for(i=head[u];i!=-1;i=edge[i].next) { v=edge[i].v; if(edge[i].c>0&&dis[v]<mindis) { cur[u]=i; mindis=dis[v]; } } if((--gap[dis[u]])==0)break; gap[dis[u]=mindis+1]++; u=pre[u]; } return maxflow; } int n,m; int mp[1010][50]; int cap[50]; int src,dest; void build() { src=0;dest=n+m+1; memset(head,-1,sizeof(head)); E=0; int i; for(i=1;i<=n;i++) add_edge(src,i,1,0); for(i=1;i<=m;i++) add_edge(i+n,dest,cap[i],0); } int solve() { int i,j,k,ans; for(ans=1;ans<=m;ans++) { for(k=1;ans+k-1<=m;k++) { build(); for(i=1;i<=n;i++) { for(j=k;j<k+ans;j++) { add_edge(i,mp[i][j]+n,1,0); } } if(SAP(0,n+m+1,n+m+2)==n) return ans; } } return m; } int main() { int i,j; while(scanf("%d%d",&n,&m)!=EOF) { for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { scanf("%d",&mp[i][j]); } } for(i=1;i<=m;i++) scanf("%d",&cap[i]); printf("%d\n",solve()); } return 0; }