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;
}
posted @ 2012-04-10 20:29  Because Of You  Views(296)  Comments(0Edit  收藏  举报