最大流邻接表spa

来源:互联网 发布:linux常用命令面试题 编辑:程序博客网 时间:2024/06/05 02:26
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define MAXN 4444
#define MAXM 999999
#define inf 1<<30


struct Edge
{
    int v,cap,next;
} edge[MAXM];


int n,m,vs,vt,NE,NV,Min;
int head[MAXN];


void Insert(int u,int v,int cap)
{
    edge[NE].v=v;
    edge[NE].cap=cap;
    edge[NE].next=head[u];
    head[u]=NE++;


    edge[NE].v=u;
    edge[NE].cap=0;
    edge[NE].next=head[v];
    head[v]=NE++;
}


int level[MAXN];
int gap[MAXN];


void bfs(int vt)
{
    memset(level,-1,sizeof(level));
    memset(gap,0,sizeof(gap));
    level[vt]=0;
    gap[level[vt]]++;
    queue<int>que;
    que.push(vt);
    while(!que.empty())
    {
        int u=que.front();
        que.pop();
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].v;
            if(level[v]!=-1) continue;
            level[v]=level[u]+1;
            gap[level[v]]++;
            que.push(v);


        }
    }
}




int pre[MAXN];
int cur[MAXN];
//参数  起点  终点
int SAP(int vs,int vt)
{
    bfs(vt);
    memset(pre,-1,sizeof(pre));
    memcpy(cur,head,sizeof(head));
    int u=pre[vs]=vs,flow=0,aug=inf;
    gap[0]=NV;
    while(level[vs]<NV)
    {
        bool flag=false;
        for(int &i=cur[u]; i!=-1; i=edge[i].next)  //i是别名  i改变cur也改变  不走已经走过的道路
        {
            int v=edge[i].v;
            if(edge[i].cap&&level[u]==level[v]+1)
            {
                flag=true;
                pre[v]=u;
                u=v;
                //  aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
                aug=min(aug,edge[i].cap);
                if(v==vt)
                {
                    flow+=aug;
                    for(u=pre[v]; v!=vs; v=u,u=pre[u])
                    {
                        edge[cur[u]].cap-=aug;
                        edge[cur[u]^1].cap+=aug;
                    }
                    //     aug=-1;
                    aug=inf;
                }
                break;
            }
        }
        if(flag)continue;
        int minlevel=NV;
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].v;
            if(edge[i].cap&&level[v]<minlevel)
            {
                minlevel=level[v];
                cur[u]=i;
            }
        }
        if(--gap[level[u]]==0)break;
        level[u]=minlevel+1;
        gap[level[u]]++;
        u=pre[u];
    }
    return flow;
}




int main()
{
    int u,v,w,w1,w2;
    int mm[30];
    int Map[1010][30];
    while(~scanf("%d%d",&n,&m))
    {
        vs=0;//起点
        vt=n+m+1;//终点
        NV=n+m+2;//可能走过的边的总数
        NE=0;
        Min=inf;
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
            {
                scanf("%d",&Map[i][j]);
            }
        }
        for(int i=1; i<=m; i++)
        {
            scanf("%d",&mm[i]);
        }




        for(int i=1; i<=m; i++)
        {
            for(int j=i; j<=m; j++)
            {
                memset(head,-1,sizeof(head));
                NE=0;
                for(int k=1; k<=n; k++)
                {
                    Insert(0,k,1);
                }


                for(int k=1; k<=m; k++)
                {
                    Insert(n+k,n+m+1,mm[k]);
                }


                for(int k=1; k<=n; k++)
                {
                    for(int l=i; l<=j; l++)
                    {
                        Insert(k,n+Map[k][l],1);
                    }
                }
                if(SAP(vs,vt)==n)
                {
                    //cout<<i<<" "<<j<<endl;
                    Min=min(j-i+1,Min);
                }
            }
        }


        printf("%d\n",Min);
    }
    return 0;
}
0 0
原创粉丝点击