poj 2396 zoj 1994 Budget(有源汇上下界的可行流)

思路:

无源汇 (附加源汇+最大解决)

有源汇 (附加(T,S)->无源汇)



Budget
Time Limit: 3000MS
Memory Limit: 65536K
Total Submissions: 6237
Accepted: 2367
Special Judge

Description

We are supposed to make a budget proposal for this multi-site competition. The budget proposal is a matrix where the rows represent different kinds of expenses and the columns represent different sites. We had a meeting about this, some time ago where we discussed the sums over different kinds of expenses and sums over different sites. There was also some talk about special constraints: someone mentioned that Computer Center would need at least 2000K Rials for food and someone from Sharif Authorities argued they wouldn't use more than 30000K Rials for T-shirts. Anyway, we are sure there was more; we will go and try to find some notes from that meeting. 

And, by the way, no one really reads budget proposals anyway, so we'll just have to make sure that it sums up properly and meets all constraints.

Input

The first line of the input contains an integer N, giving the number of test cases. The next line is empty, then, test cases follow: The first line of each test case contains two integers, m and n, giving the number of rows and columns (m <= 200, n <= 20). The second line contains m integers, giving the row sums of the matrix. The third line contains n integers, giving the column sums of the matrix. The fourth line contains an integer c (c < 1000) giving the number of constraints. The next c lines contain the constraints. There is an empty line after each test case. 

Each constraint consists of two integers r and q, specifying some entry (or entries) in the matrix (the upper left corner is 1 1 and 0 is interpreted as "ALL", i.e. 4 0 means all entries on the fourth row and 0 0 means the entire matrix), one element from the set {<, =, >} and one integer v, with the obvious interpretation. For instance, the constraint 1 2 > 5 means that the cell in the 1st row and 2nd column must have an entry strictly greater than 5, and the constraint 4 0 = 3 means that all elements in the fourth row should be equal to 3.

Output

For each case output a matrix of non-negative integers meeting the above constraints or the string "IMPOSSIBLE" if no legal solution exists. Put one empty line between matrices.

Sample Input

2

2 3 
8 10 
5 6 7 
4 
0 2 > 2 
2 1 = 3 
2 3 > 2 
2 3 < 5 

2 2 
4 5 
6 7 
1 
1 1 > 10

Sample Output

2 3 3 
3 3 4 

IMPOSSIBLE 

一道好题

首先要根据题目要求构造出一个容量网络  然后根据网络建图跑最大流 得到可行流

容量网络的构造方法:


如图  构造一个源点s(0) 一个汇点t(n+m+1) 源点与每行的节点建边 权值为每行的总和

每列的节点与汇点之间建边  权值为每列的总和

每行每列之间有上下界 根据题目的要求求出low[i][j] high[i][j] 

然后判断有木有不合理的情况 不合理的直接输出IMPOSSIBLE

之后开始建图求最大流

超级源点ss(n+m+2) 超级汇点tt(n+m+3)

每行的节点i与每列的节点j连接 i->j权值为high[i][j]-low[i][j]

容量网络里的每个点与ss或tt连接  out[i]为正与ss连接 权值为out[i]

out[i]为负与tt连接 权值为-out[i]

容量网络中s t之间也要建边 t->s权值INF

细节部门就是数据的读取处理出low[i][j] high[i][j] out[i]


<span style="font-family:KaiTi_GB2312;font-size:18px;">#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <queue>
#include <vector>

#define MEM(a,x) memset(a,x,sizeof a)
#define eps 1e-8
#define MOD 10009
#define MAXN 10010
#define INF 0x3fffffff
#define ll __int64
#define bug cout<<"here"<<endl;
#define fread freopen("ceshi.txt","r",stdin)
#define fwrite freopen("out.txt","w",stdout)

using namespace std;

void read(int &x)
{
    char ch;
    x=0;
    while(ch=getchar(),ch!=' '&&ch!='\n')
    {
        x=x*10+ch-'0';
    }
}

struct Edge
{
    int from,to,cap,flow;
    bool operator <(const Edge e) const
    {
        if(e.from!=from)  return from<e.from;
        else return to<e.to;
    }
    Edge() {}
    Edge(int from,int to,int cap,int flow):from(from),to(to),cap(cap),flow(flow) {}
};

struct Dinic
{
    vector<Edge> edges;
    vector<int> G[MAXN];
    bool vis[MAXN];//BFS使用
    int d[MAXN];   //从起点到i的距离
    int cur[MAXN]; //当前弧下标
    int n,m,s,t,maxflow;   //节点数 边数(包括反向弧) 源点编号和弧点编号

    void init(int n)
    {
        this->n=n;
        for(int i=0;i<=n;i++)
            G[i].clear();
        edges.clear();
    }

    void addedge(int from,int to,int cap)
    {
        edges.push_back(Edge(from,to,cap,0));
        edges.push_back(Edge(to,from,0,0));
        m=edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }

    bool bfs()
    {
        MEM(vis,0);
        MEM(d,-1);
        queue<int> q;
        q.push(s);
        d[s]=maxflow=0;
        vis[s]=1;
        while(!q.empty())
        {
            int u=q.front(); q.pop();
            int sz=G[u].size();
            for(int i=0;i<sz;i++)
            {
                Edge e=edges[G[u][i]];
                if(!vis[e.to]&&e.cap>e.flow)
                {
                    d[e.to]=d[u]+1;
                    vis[e.to]=1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }

    int dfs(int u,int a)
    {
        if(u==t||a==0)  return a;
        int sz=G[u].size();
        int flow=0,f;
        for(int &i=cur[u];i<sz;i++)
        {
            Edge &e=edges[G[u][i]];
            if(d[u]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0)
            {
                e.flow+=f;
                edges[G[u][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if(a==0)  break;
            }
        }
        return flow;
    }

    int Maxflow(int s,int t)
    {
        this->s=s; this->t=t;
        int flow=0;
        while(bfs())
        {
            MEM(cur,0);
            flow+=dfs(s,INF);
        }
        return flow;
    }
}Dic;

int out[250];
int low[300][300];
int high[300][300];
int r[220],c[30];

int main()
{
//    fread;
    int tc;
    scanf("%d",&tc);
    int cs=0;
    while(tc--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        MEM(out,0);
        int line=0; int col=0;
        for(int i=1;i<=n;i++)
        {
            int num;
            scanf("%d",&num);
            line+=num;
            out[0]-=num;
            out[i]+=num;
        }
        for(int j=1;j<=m;j++)
        {
            int num;
            scanf("%d",&num);
            col+=num;
            out[n+m+1]+=num;
            out[j+n]-=num;
        }//out记录进入/出去 节点的流量  为正与源点建边  为负与汇点建边
        for(int i=0;i<300;i++)
            for(int j=0;j<300;j++)
        {
            low[i][j]=0;
            high[i][j]=INF;
        }
        int ca;
        scanf("%d",&ca);
        int flag=0;
        while(ca--)
        {
            int u,v,w;
            char ch;
            scanf("%d %d %c %d",&u,&v,&ch,&w);
            if(u==0&&v==0)
            {
                for(int i=1;i<=n;i++)
                    for(int j=1;j<=m;j++)
                {
                    if(ch=='>') low[i][j+n]=max(low[i][j+n],w+1);
                    if(ch=='<') high[i][j+n]=min(high[i][j+n],w-1);
                    if(ch=='=') low[i][j+n]=high[i][j+n]=w;
                    if(low[i][j+n]>high[i][j+n])
                        flag=1;
                }
            }
            else if(u==0)
            {
                for(int i=1;i<=n;i++)
                {
                    if(ch=='>') low[i][v+n]=max(low[i][v+n],w+1);
                    if(ch=='<') high[i][v+n]=min(high[i][v+n],w-1);
                    if(ch=='=') low[i][v+n]=high[i][v+n]=w;
                    if(low[i][v+n]>high[i][v+n])
                        flag=1;
                }
            }
            else if(v==0)
            {
                for(int j=1;j<=m;j++)
                {
                    if(ch=='>') low[u][j+n]=max(low[u][j+n],w+1);
                    if(ch=='<') high[u][j+n]=min(high[u][j+n],w-1);
                    if(ch=='=') low[u][j+n]=high[u][j+n]=w;
                    if(low[u][j+n]>high[u][j+n])
                        flag=1;
                }
            }
            else
            {
                if(ch=='>') low[u][v+n]=max(low[u][v+n],w+1);
                if(ch=='<') high[u][v+n]=min(high[u][v+n],w-1);
                if(ch=='=') low[u][v+n]=high[u][v+n]=w;
                if(low[u][v+n]>high[u][v+n])
                        flag=1;
            }
        }
        if(cs) puts("");
        cs=1;
        if(flag||line!=col)
        {
            puts("IMPOSSIBLE");
            continue;
        }
        int s=n+m+2,t=n+m+3;
        Dic.init(t);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                out[i]-=low[i][j+n];
                out[j+n]+=low[i][j+n];
                Dic.addedge(i,j+n,high[i][j+n]-low[i][j+n]);
            }
        }
        Dic.addedge(n+m+1,0,INF);
        int sum=0;
        for(int i=0;i<=n+m;i++)
        {
            if(out[i]>0)
            {
                sum+=out[i];
                Dic.addedge(s,i,out[i]);
            }
            else
                Dic.addedge(i,t,-out[i]);
        }
        int mx=Dic.Maxflow(s,t);
//        cout<<mx<<endl;
//        cout<<"sum "<<sum<<endl;
//        int ffff=(Dic.Maxflow(s,t)==sum);
//        cout<<ffff<<endl;
        if(mx!=sum)
        {
//            bug;
            puts("IMPOSSIBLE");
            continue;
        }
//        for(int i=0;i<n*m;i++)
//        {
//            int u=Dic.edges[i*2].from,v=Dic.edges[i*2].to;
//            cout<<"iii "<<i<<endl;
//            cout<<u<<" "<<v<<"  "<<Dic.edges[i*2].flow+low[u][v]<<endl;
//        }
        int id=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(j==1)
                {
                    printf("%d",Dic.edges[id*2].flow+low[i][j+n]);
                }
                else
                    printf(" %d",Dic.edges[id*2].flow+low[i][j+n]);
                id++;
            }
            printf("\n");
        }
//        if(tc)
//            puts("");
    }
    return 0;
}
</span>







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值