zoukankan      html  css  js  c++  java
  • ZOJ1994 & POJ2396:Budget——题解

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1994

    http://poj.org/problem?id=2396

    题目大意:给一个m行n列的空矩阵,让你往上面填数(数为非负整数),使得这个矩阵满足:

    1.每行/列和等于给定的每行/列和

    2.一些限制条件。

    限制条件限制了x,y,ch,v,使得x行y列的点的数满足(>or=or<,由ch决定)v。

    特别的,如果x=0则代表y列全满足该条件,如果y=0则代表x行全满足该条件,如果全为0则代表全矩阵全满足该条件。

    ——————————————————————————

    有二分图+上下界网络流想法,不难想到先建源汇点,源点到所有的行连一条上下界均为行和的边,所有的列到汇点连一条上下界均为列和的边。

    然后整理限制条件,行和列之间连满足所有限制条件的边。

    在那之后就是上下界网络流的活了。

    注意:

    1.可以先判断行和之和如果不等于列和之和的话就是IMPOSSIBLE。

    2.限制条件如果不满足的话||第一条发生的话,记得把剩余的限制条件读完再输出。

    3.我们其实可以简化,我们其实根本不需要源汇点,于是它其实可以转换成无源汇上下界网络流可行流。

    原因:最开始建源汇点的时候我们发现它只连了上下界相同的边,相当于没连,以致到后来跑可行流的时候它根本不会做出任何贡献,所以大可以删掉。

    4.IMPOSSIBLE不要打错……

    5.ZOJ选手注意,不能填负数,最后一行不能有两个回车。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=405;
    const int M=2000005;
    const int INF=1e9;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct node{
        int nxt,to,w;
    }edge[M];
    int head[N],du[N],up[205][205],low[205][205];
    int cnt=-1,S,T;
    bool die[205][205];
    inline void add(int u,int v,int w){
        cnt++;
        edge[cnt].to=v;
        edge[cnt].w=w;
        edge[cnt].nxt=head[u];
        head[u]=cnt;
        return;
    }
    int lev[N],cur[N],dui[N];
    bool bfs(int k){
        int r=0;
        for(int i=1;i<=k;i++){
        lev[i]=-1;
        cur[i]=head[i];
        }
        dui[0]=S,lev[S]=0;
        int u,v;
        for(int l=0;l<=r;l++){
        u=dui[l];
        for(int e=head[u];e!=-1;e=edge[e].nxt){
            v=edge[e].to;
            if(edge[e].w>0&&lev[v]==-1){
            lev[v]=lev[u]+1;
            r++;
            dui[r]=v;
            if(v==T)return 1;
            }
        }
        }
        return 0;
    }
    int dinic(int u,int flow,int k){
        if(u==k)return flow;
        int res=0,delta;
        for(int &e=cur[u];e!=-1;e=edge[e].nxt){
        int v=edge[e].to;
        if(edge[e].w>0&&lev[u]<lev[v]){ 
            delta=dinic(v,min(edge[e].w,flow-res),k); 
            if(delta>0){
            edge[e].w-=delta;
            edge[e^1].w+=delta;
            res+=delta;
            if(res==flow)break; 
            }
        }
        }
        if(res!=flow)lev[u]=-1;
        return res;
    }
    inline void init(int m,int n){
        memset(head,-1,sizeof(head));
        memset(du,0,sizeof(du));
        memset(die,0,sizeof(die));
        for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            up[i][j]=INF;
            low[i][j]=0;
        }
        }
        cnt=-1;
        return;
    }
    inline char getc(){
        char ch=' ';
        while(ch==' ')ch=getchar();
        return ch;
    }
    int main(){
        int t=read(),num=0;
        while(t--){
            num++;
            if(num>1)puts("");
        int m=read(),n=read();
            init(m,n);
        int tot=0;
        for(int i=1;i<=m;i++){
            int h=read();
            du[i]+=h;
            tot+=h;
        }
        for(int i=1;i<=n;i++){
            int l=read();
            du[i+m]-=l;
            tot-=l;
        }
        int c=read();
        bool flag=1;
        for(int i=1;i<=c;i++){
            int r=read(),q=read(),a,b;
            char ch=getc();
            int v=read();
            if(ch=='<'){a=0;b=--v;}
            else if(ch=='>'){a=++v;b=INF;}
            else a=b=v;
            if(!r&&!q){
            for(int j=1;j<=m&&flag;j++){
                for(int k=1;k<=n&&flag;k++){
                if(die[j][k]&&(low[j][k]>b||low[j][k]<a)){
                    flag=0;
                    break;
                }
                if(ch=='='){up[j][k]=low[j][k]=v;die[j][k]=1;}
                else if(ch=='>')low[j][k]=max(low[j][k],v);
                else up[j][k]=min(up[j][k],v);
                if(low[j][k]>up[j][k])flag=0;
                }
            }
            }else if(!r){
            for(int j=1;j<=m&&flag;j++){
                if(die[j][q]&&(low[j][q]>b||low[j][q]<a)){
                flag=0;
                break;
                }
                if(ch=='='){up[j][q]=low[j][q]=v;die[j][q]=1;}
                else if(ch=='>')low[j][q]=max(low[j][q],v);
                else up[j][q]=min(up[j][q],v);
                if(low[j][q]>up[j][q])flag=0;
            }
            }else if(!q){
            for(int k=1;k<=n&&flag;k++){
                if(die[r][k]&&(low[r][k]>b||low[r][k]<a)){
                flag=0;
                break;
                }
                if(ch=='='){up[r][k]=low[r][k]=v;die[r][k]=1;}
                else if(ch=='>')low[r][k]=max(low[r][k],v);
                else up[r][k]=min(up[r][k],v);
                if(low[r][k]>up[r][k])flag=0;
            }
            }else{
            if(die[r][q]&&(low[r][q]>b||low[r][q]<a)){
                flag=0;
            }
            if(ch=='='){up[r][q]=low[r][q]=v;die[r][q]=1;}
            else if(ch=='>')low[r][q]=max(low[r][q],v);
            else up[r][q]=min(up[r][q],v);
            if(low[r][q]>up[r][q])flag=0;
            }
        }
        if(!flag||tot!=0){
            puts("IMPOSSIBLE");
            continue;
        }
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++){
            add(i,j+m,up[i][j]-low[i][j]);
            add(j+m,i,0);
            du[i]-=low[i][j];
            du[j+m]+=low[i][j];
            }
        }
        S=m+n+1;T=S+1;
        int ans=0,full=0;
        for(int i=1;i<=m+n;i++){
            if(du[i]>0){
            add(S,i,du[i]);
            add(i,S,0);
            full+=du[i];
            }else if(du[i]<0){
            add(i,T,-du[i]);
            add(T,i,0);
            }
        }
        while(bfs(T))ans+=dinic(S,INF,T);
        if(ans!=full)puts("IMPOSSIBLE");
        else{
            for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++){
                int id=((i-1)*n+j)*2-1;
                printf("%d",low[i][j]+edge[id].w);
                if(j!=n)putchar(' ');
            }
            puts("");
            }
        }
        }
        return 0;
    }
  • 相关阅读:
    nginx启动时指定配置文件
    idea修改忽视文件产生得bug
    SpringBoot整合RabbitMQ出现org.springframework.amqp.AmqpException: No method found for class
    解决git速度太慢的问题,亲测有效
    HttpRequestException encountered解决方法
    mybatis大于等于小于等于的写法
    Could not initialize class sun.awt.X11GraphicsEnvironment异常处理
    CF377C Captains Mode
    AT1251 たのしいたのしい家庭菜園
    CF1057C Tanya and Colored Candies
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8227432.html
Copyright © 2011-2022 走看看