zoukankan      html  css  js  c++  java
  • bzoj 2406: 矩阵 上下界网络流判定

    2406: 矩阵

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 138  Solved: 46
    [Submit][Status][Discuss]

    Description

     

    Input

    第一行两个数nm,表示矩阵的大小。

    接下来n行,每行m列,描述矩阵A

    最后一行两个数LR

    Output

    第一行,输出最小的答案;

    Sample Input

    2 2

    0 1

    2 1

    0 1

    Sample Output

    1

    HINT

    对于100%的数据满足N,M<=200,0<=L<=R<=1000,0<=Aij<=1000

     

      看网上没什么题解,就随便写一写吧,二分答案转化为判定问题:构造矩阵,使得每行每列之和分别满足在一个区间内,这就是很裸很裸的带下界网络流判定问题。直接行列分别建点即可,然而我写的时候数组开小了,wa了一个上午。

     

     

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define MAXN 220
    #define MAXV MAXN*MAXN
    #define MAXE MAXV*2
    #define INF 0x3f3f3f3f
    #define BIG 100000000
    #define abs(x) ((x)<0?(-(x)):(x))
    struct Edge
    {
            int val,np;
            Edge *next,*neg;
    }E[MAXE],*V[MAXV];
    int tope=1;
    int sour=0,sink=1;
    inline void addedge(int x,int y,int z)
    {
        //    cout<<"Add edge:<"<<tope+1<<">"<<x<<" "<<y<<":"<<z<<endl;
            E[++tope].np=y;
            E[tope].val=z;
            E[tope].next=V[x];
            V[x]=&E[tope];
    
            E[++tope].np=x;
            E[tope].val=0;
            E[tope].next=V[y];
            V[y]=&E[tope];
    
            E[tope].neg=&E[tope-1];
            E[tope-1].neg=&E[tope];
    }
    int q[MAXV],lev[MAXV];
    int vis[MAXV],bfstime=0;
    bool bfs()
    {
            int head=-1,tail=0;
            Edge *ne;
            lev[sour]=1;
            vis[sour]=++bfstime;
            q[0]=sour;
            while (head<tail)
            {
                    for (ne=V[q[++head]];ne;ne=ne->next)
                    {
                            if (!ne->val || vis[ne->np]==bfstime)continue;
                            q[++tail]=ne->np;
                            vis[ne->np]=bfstime;
                            lev[ne->np]=lev[q[head]]+1;
                    }
            }
            return vis[sink]==bfstime;
    }
    int dfs(int now,int maxf)
    {
            int ret=0,t;
            if (now==sink || !maxf)return maxf;
            Edge* ne;
            for (ne=V[now];ne;ne=ne->next)
            {
                    if (!ne->val || lev[ne->np]!=lev[now]+1)continue;
                    t=dfs(ne->np,min(maxf,ne->val));
                    ne->val-=t;
                    ne->neg->val+=t;
                    maxf-=t;
                    ret+=t;
                    //cout<<"Flow:"<<now<<"-"<<ne->np<<":"<<x<<"("<<ne->val<<")"<<endl;
            }
            if (!ret)lev[now]=-1;
            return ret;
    }
    int dinic()
    {
            int ret=0;
            while (bfs())
            {
                    ret+=dfs(sour,INF);
            }
            return ret;
    }
    
    int mat[MAXN][MAXN];
    int degin[MAXV],degout[MAXV];
    int main()
    {
            freopen("input.txt","r",stdin);
            freopen("output.txt","w",stdout);
            int n,m,a,b;
            scanf("%d%d",&n,&m);
            for (int i=0;i<n;i++)
                    for (int j=0;j<m;j++)
                    {
                            scanf("%d",&mat[i][j]);
                    }
            scanf("%d%d",&a,&b);
            int l=-1,r=100010;
            int tsour=2,tsink=3;
            while (l+1<r)
            {
                    memset(degin,0,sizeof(degin));
                    memset(degout,0,sizeof(degout));
                    memset(V,0,sizeof(V));
                    tope=-1;
                    int mid=(l+r)>>1;
                    for (int i=0;i<n;i++)
                    {
                            int s=0;
                            for (int j=0;j<m;j++)
                                    s+=mat[i][j];
                            degout[tsour]+=s-mid;
                            degin[4+i]+=s-mid;
                            addedge(tsour,4+i,mid*2);
                    }
                    for (int i=0;i<m;i++)
                    {
                            int s=0;
                            for (int j=0;j<n;j++)
                                    s+=mat[j][i];
                            degin[tsink]+=s-mid;
                            degout[4+i+n]+=s-mid;
                            addedge(4+i+n,tsink,mid*2);
                    }
                    for (int i=0;i<n;i++)
                    {
                            for (int j=0;j<m;j++)
                            {
                                    degout[4+i]+=a;
                                    degin[4+j+n]+=a;
                                    addedge(4+i,4+j+n,b-a);
                            }
                    }
                    addedge(tsink,tsour,BIG);
                    int sum=0;
                    for (int i=2;i<4+n+m;i++)
                    {
                            if (degout[i]>degin[i])
                            {
                                    sum+=degout[i]-degin[i];
                                    addedge(i,sink,degout[i]-degin[i]);
                            }
                            else if (degin[i]>degout[i])
                                    addedge(sour,i,degin[i]-degout[i]);
                    }
                    if (dinic()==sum)
                            r=mid;
                    else
                            l=mid;
            }
            printf("%d
    ",r);
    }

     

     

  • 相关阅读:
    招聘asp.net mvc, C#软件开发
    成功后面是付出===来硅谷三个月来第一篇关于硅谷的文章
    招聘Web前端开发
    记人之长,忘人之短;谈人之善,容人之过
    如何减少Outlook占用空间
    流程管理误区
    在Windows Server 2008上安装 Windows SharePoint Services 3.0
    在WinXP or Vista上开发Webpart
    成功后面是付出===来硅谷三个月来第一篇关于硅谷的文章(续篇)
    poj 2362 hdoj 1518 Square(搜索)
  • 原文地址:https://www.cnblogs.com/mhy12345/p/4548859.html
Copyright © 2011-2022 走看看