zoukankan      html  css  js  c++  java
  • poj2396 Budget

    题目描述:

    $T$组询问,每次给出$m,n,q$以及$q$组限制,求一个$m*n$的矩阵,满足:

    1. 每一行/列之和等于给出的每一行/列之和。
    2. 对于每组限制$(x,y,op,w)$(若$x$或$y$为$0$则代表一整行/列),满足所有限制中的元素都大于/等于/小于$w$。

    题解:

    有源汇有上下界可行流板子题+墙题。

    每一行/列都看作一个点$x$。矩阵里的数就是相连的边权。

    对于限制$1$,可以看作$S$连$x$/$x$连$T$的边上下界都为给出值$k$;

    对于限制$2$,可以看作$x$与$y$相连的边上下界修改。

    最后按有源汇可行流套路建图即可。

    注意$x$可能连$y$,也可能连旧源汇和新源汇……

    代码:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 350;
    const int inf = 0x3f3f3f3f;
    const ll  Inf = 0x3f3f3f3f3f3f3f3fll;
    template<typename T>
    inline void read(T&x)
    {
        T f = 1,c = 0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x = f*c;
    }
    int _,m,n,Q,S,T,SS,TT,hed[N],cnt=1;
    ll v1[N][2],v2[N][2],v3[N][N][2],v4[2],s[2][N],fin[N],fout[N];
    void chkmax(ll&x,ll y){if(x<y)x=y;}
    void chkmin(ll&x,ll y){if(x>y)x=y;}
    char op[10];
    void orz(){puts("IMPOSSIBLE");}
    void clear()
    {
        memset(hed,0,sizeof(hed));
        memset(fin,0,sizeof(fin));
        memset(fout,0,sizeof(fout));
        for(int i=1;i<=m;i++)
            v1[i][0]=0,v1[i][1]=Inf;
        for(int i=1;i<=n;i++)
            v2[i][0]=0,v2[i][1]=Inf;
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                v3[i][j][0]=0,v3[i][j][1]=Inf;
        v4[0] = 0,v4[1] = Inf;
        cnt = 1;
        S = n+m+1,T = S+1,SS = T+1,TT = SS+1;
    }
    struct EG
    {
        int to,nxt;
        ll fl;
    }e[60*N];
    void ae(int f,int t,ll fl)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        e[cnt].fl = fl;
        hed[f] = cnt;
    }
    void AE(int f,int t,ll fl)
    {
        ae(f,t,fl);
        ae(t,f,0);
    }
    int cur[N],dep[N];
    bool vis[N];
    bool bfs()
    {
        queue<int>q;
        memcpy(cur,hed,sizeof(cur));
        memset(dep,0x3f,sizeof(dep));
        dep[SS] = 0,vis[SS] = 1;q.push(SS);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            for(int j=hed[u];j;j=e[j].nxt)
            {
                int to = e[j].to;
                if(e[j].fl&&dep[to]>dep[u]+1)
                {
                    dep[to] = dep[u]+1;
                    if(!vis[to])vis[to]=1,q.push(to);
                }
            }
            vis[u] = 0;
        }
        return dep[TT]!=inf;
    }
    ll dfs(int u,ll lim)
    {
        if(u==TT||!lim)return lim;
        ll fl = 0,f;
        for(int j=cur[u];j;j=e[j].nxt)
        {
            cur[u] = j;
            int to = e[j].to;
            if(dep[to]==dep[u]+1&&(f=dfs(to,min(lim,e[j].fl))))
            {
                fl+=f,lim-=f;
                e[j].fl-=f,e[j^1].fl+=f;
                if(!lim)break;
            }
        }
        return fl;
    }
    ll dinic()
    {
        ll ret = 0;
        while(bfs())ret+=dfs(SS,Inf);
        return ret;
    }
    int main()
    {
    //    freopen("tt.in","r",stdin);
        read(_);
        while(_--)
        {
            read(m),read(n);
            clear();
            for(int i=1;i<=m;i++)
                read(s[0][i]);
            for(int i=1;i<=n;i++)
                read(s[1][i]);
            read(Q);
            ll w;
            for(int x,y,i=1;i<=Q;i++)
            {
                read(x),read(y);
                scanf("%s",op+1);
                read(w);
                if(op[1]=='=')
                {
                    if(x&&y)chkmax(v3[x][y][0],w),chkmin(v3[x][y][1],w);
                    else if(!x&&y)chkmax(v2[y][0],w),chkmin(v2[y][1],w);
                    else if(x&&!y)chkmax(v1[x][0],w),chkmin(v1[x][1],w);
                    else chkmax(v4[0],w),chkmin(v4[1],w);
                }else if(op[1]=='<')
                {
                    w--;
                    if(x&&y)chkmin(v3[x][y][1],w);
                    else if(!x&&y)chkmin(v2[y][1],w);
                    else if(x&&!y)chkmin(v1[x][1],w);
                    else chkmin(v4[1],w);
                }else
                {
                    w++;
                    if(x&&y)chkmax(v3[x][y][0],w);
                    else if(!x&&y)chkmax(v2[y][0],w);
                    else if(x&&!y)chkmax(v1[x][0],w);
                    else chkmax(v4[0],w);
                }
            }
            bool ORZ = 0;
            if(v4[0]>v4[1])ORZ=1;
            for(int i=1;!ORZ&&i<=m;i++)
            {
                chkmax(v1[i][0],v4[0]);
                chkmin(v1[i][1],v4[1]);
                if(v1[i][0]>v1[i][1])ORZ=1;
            }
            for(int i=1;!ORZ&&i<=n;i++)
            {
                chkmax(v2[i][0],v4[0]);
                chkmin(v2[i][1],v4[1]);
                if(v2[i][0]>v2[i][1])ORZ=1;
            }
            for(int i=1;!ORZ&&i<=m;i++)
                for(int j=1;!ORZ&&j<=n;j++)
                {
                    chkmax(v3[i][j][0],max(v1[i][0],v2[j][0]));
                    chkmin(v3[i][j][1],min(v1[i][1],v2[j][1]));
                    if(v3[i][j][0]>v3[i][j][1])ORZ=1;
                }
            if(ORZ){orz();continue;}
            
            ll sum = 0;
            for(int i=1;i<=m;i++)
                AE(S,i,0),fin[i]+=s[0][i],fout[S]+=s[0][i];
            for(int i=1;i<=n;i++)
                AE(i+m,T,0),fin[T]+=s[1][i],fout[i+m]+=s[1][i];
            for(int i=1;i<=m;i++)
                for(int j=n;j>=1;j--)
                    AE(i,j+m,v3[i][j][1]-v3[i][j][0]),fin[j+m]+=v3[i][j][0],fout[i]+=v3[i][j][0];
            AE(T,S,Inf);
            for(int i=1;i<=T;i++)
                if(fin[i]>fout[i])AE(SS,i,fin[i]-fout[i]),sum+=fin[i]-fout[i];
                else AE(i,TT,fout[i]-fin[i]);
            
            if(sum!=dinic()){orz();continue;}
            else
            {
                for(int i=1;i<=m;puts(""),i++)
                    for(int j=hed[i],to;j;j=e[j].nxt)if((to=e[j].to)!=SS&&to!=S&&to!=TT)
                        printf("%lld ",v3[i][to-m][1]-e[j].fl);
                puts("");
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    一步一步学习IdentityServer4 (4) 处理特殊需求之-登录等待页面
    php 打包下载
    nginx https反向代理tomcat
    the "ssl" parameter requires ngx_http_ssl_module in /usr/local/nginx/conf/nginx.conf
    layui配置
    vue 学习一
    MyCAT+MySQL 搭建高可用企业级数据库集群——第3章 MyCat核心配置讲解
    第一模块·开发基础-第3章 作业讲解
    《扭转人生的40个哲学提问》 徐帆 著
    零基础学 JavaScript 全彩版 明日科技 编著
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10746910.html
Copyright © 2011-2022 走看看