现在的位置: 首页 > 综合 > 正文

POJ2396&ZOJ1994–Budget【有源汇上下界可行流】

2018年04月24日 ⁄ 综合 ⁄ 共 3512字 ⁄ 字号 评论关闭

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

题意:给一个n*m的矩阵,给出每行的总和以及每列的总和,再给出某些位置的最小或最大限制,问是否存在可能的矩阵,如果存在输出一种矩阵信息。

思路:这是一个有源汇的上下界可行流,对于这种题,从汇点连一条弧到源点,容量为INF,这不会影响流量平衡条件,并且此时原图转换为了无源汇的上下界可行流,剩下的做法和无源汇一样。

建图:原图源点src连向每个行顶点,容量为每行的和,每个列顶点连向汇点,容量为每个列顶点的和,行顶点和列顶点间也各有一条弧,初始容量无下界、无上界,输入时再更新。最后连一条汇点指向源点的容量为INF的弧,剩下就是无源汇的做法。

这道题细节还是挺多的,初始化挫了WA出了翔。还有我在POJ上C++交TLE了,去ZOJ上交却过了,再回POJ用G++交才AC,不明觉厉。

isap代码

#include<cstring>
#include<string>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 100100
#define eps 1e-7
#define INF 0x7FFFFFFF
#define seed 131
#define ll long long
#define ull unsigned ll
#define lson l,m,rt<<1
#define rson r,m+1,rt<<1|1

struct node{
    int u,v,w,next;
}edge[20000];
int head[250],dist[250],cur[250],fa[250],num[250];
int low[300][300],upp[300][300],D[250];
int n,m,cnt,nn,src,sink,supersrc,supersink;

void add_edge(int a,int b,int c){
    edge[cnt].u = a;
    edge[cnt].v = b;
    edge[cnt].w = c;
    edge[cnt].next = head[a];
    head[a] = cnt++;
}
void build_graph(){
    int i,j;
    for(i=1;i<=n;i++){
        for(j=n+1;j<=n+m;j++){
            D[i] -= low[i][j];
            D[j] += low[i][j];
            add_edge(i,j,upp[i][j]-low[i][j]);
            add_edge(j,i,0);
        }
    }
    add_edge(sink,src,INF);
    add_edge(src,sink,0);
    for(i=0;i<=n+m+1;i++){
        if(D[i]==0) continue;
        else if(D[i]>0){
            add_edge(supersrc,i,D[i]);
            add_edge(i,supersrc,0);
        }
        else{
            add_edge(i,supersink,-D[i]);
            add_edge(supersink,i,0);
        }
    }
}
void bfs()
{
    int x,i,j;
    queue<int> q;
    memset(dist,-1,sizeof(dist));
    q.push(supersink);
    dist[supersink] = 0;
    while(!q.empty()){
        x = q.front();
        q.pop();
        for(i=head[x];i!=-1;i=edge[i].next){
            if(dist[edge[i].v]<0){
                dist[edge[i].v] = dist[x] + 1;
                q.push(edge[i].v);
            }
        }
    }
}

int augment()
{
    int x=supersink,a=INF;
    while(x!=supersrc){
        a = min(a,edge[fa[x]].w);
        x = edge[fa[x]].u;
    }
    x=supersink;
    while(x!=supersrc){
        edge[fa[x]].w -= a;
        edge[fa[x]^1].w += a;
        x = edge[fa[x]].u;
    }
    return a;
}

int isap()
{
    int i,x,ok,minm,flow=0;
    memset(num,0,sizeof(num));
    bfs();
    for(i=0;i<=nn+1;i++) num[dist[i]]++;
    for(i=0;i<=nn+1;i++) cur[i] = head[i];
    x=supersrc;
    while(dist[supersrc]<nn){
        if(x==supersink){
            flow += augment();
            x = supersrc;
        }
        ok=0;
        for(i=cur[x];i!=-1;i=edge[i].next){
            if(edge[i].w && dist[x]==dist[edge[i].v]+1){
                ok=1;
                fa[edge[i].v] = i;
                cur[x] = i;
                x = edge[i].v;
                break;
            }
        }
        if(!ok){
            minm = nn;
            for(i=head[x];i!=-1;i=edge[i].next)
                if(edge[i].w && dist[edge[i].v]<minm)   minm=dist[edge[i].v];
            if(--num[dist[x]]==0)break;
            num[dist[x]=minm+1]++;
            cur[x]=head[x];
            if(x!=supersrc)  x=edge[fa[x]].u;
        }
    }
    return flow;
}

int main(){
    int t,q,i,j;
    int a,b,c,d;
    char str[5];
    scanf("%d",&t);
    int cas = 0;
    while(t--){
        if(!cas)    cas = 1;
        else    puts("");
        scanf("%d%d",&n,&m);
        memset(head,-1,sizeof(head));
        memset(D,0,sizeof(D));
        cnt = 0;
        src = 0;
        sink = n + m + 1;
        supersrc = sink + 1;
        supersink = sink + 2;
        nn = sink + 3;
        for(i=0;i<=n+3;i++){
            for(j=n+1;j<=n+m+3;j++){
                low[i][j] = 0;
                upp[i][j] = INF;
            }
        }
        for(i=1;i<=n;i++){
            scanf("%d",&a);
            D[src] -= a;
            D[i] += a;
        }
        for(i=n+1;i<=n+m;i++){
            scanf("%d",&a);
            D[i] -= a;
            D[sink] += a;
        }
        int r1,r2,c1,c2;
        scanf("%d",&q);
        while(q--){
            scanf("%d%d%s%d",&a,&b,str,&c);
            if(a==0){
                r1 = 1;
                r2 = n;
            }
            else    r1 = r2 = a;
            if(b==0){
                c1 = n + 1;
                c2 = n + m;
            }
            else    c1 = c2 = b + n;
            for(i=r1;i<=r2;i++){
                for(j=c1;j<=c2;j++){
                    if(str[0]=='<') upp[i][j] = min(c-1,upp[i][j]);
                    else if(str[0]=='>')    low[i][j] = max(c+1,low[i][j]);
                    else{
                        low[i][j] = max(c,low[i][j]);
                        upp[i][j] = min(c,upp[i][j]);
                    }
                }
            }
        }
        build_graph();
        isap();
        int flag = 0;
        for(i=head[supersrc];i!=-1;i=edge[i].next){
            if(edge[i].w!=0){
                flag = 1;
                break;
            }
        }
        if(flag)    puts("IMPOSSIBLE");
        else{
            for(i=1;i<=n;i++){
                for(j=1;j<m;j++){
                    printf("%d ",edge[(((i-1)*m+j-1)*2)^1].w+low[i][j+n]);
                }
                printf("%d\n",edge[(((i-1)*m+j-1)*2)^1].w+low[i][j+n]);
            }
        }
    }
    return 0;
}

抱歉!评论已关闭.