poj 2396 Budget(可行流)

来源:互联网 发布:设计师常用的软件 编辑:程序博客网 时间:2024/06/03 17:44

               直接按求可行流的方法建图,然后求一遍最大流,判断一下就可以了。。

#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdio>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#define LL long long#define CLR(a, b) memset(a, b, sizeof(a))using namespace std;const int maxn = 330;const int INF = 0x3f3f3f3f;struct Edge{    int from, to, cap, flow;    Edge() {}    Edge(int from, int to, int cap, int flow)        :from(from), to(to), cap(cap), flow(flow) {}};bool operator < (const Edge& a, const Edge& b){    return a.from < b.from || (a.from == b.from && a.to < b.to);}struct ISAP{    int n, m, s, t;    vector<Edge> edges;    vector<int> G[maxn];   // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号    bool vis[maxn];        // BFS使用    int d[maxn];           // 从起点到i的距离    int cur[maxn];        // 当前弧指针    int p[maxn];          // 可增广路上的上一条弧    int num[maxn];        // 距离标号计数    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()    {        memset(vis, 0, sizeof(vis));        queue<int> Q;        Q.push(t);        vis[t] = 1;        d[t] = 0;        while(!Q.empty())        {            int x = Q.front();            Q.pop();            for(int i = 0; i < G[x].size(); i++)            {                Edge& e = edges[G[x][i]^1];                if(!vis[e.from] && e.cap > e.flow)                {                    vis[e.from] = 1;                    d[e.from] = d[x] + 1;                    Q.push(e.from);                }            }        }        return vis[s];    }    void init(int n)    {        this->n = n;        for(int i = 0; i < n; i++) G[i].clear();        edges.clear();    }    int Augment()    {        int x = t, a = INF;        while(x != s)        {            Edge& e = edges[p[x]];            a = min(a, e.cap-e.flow);            x = edges[p[x]].from;        }        x = t;        while(x != s)        {            edges[p[x]].flow += a;            edges[p[x]^1].flow -= a;            x = edges[p[x]].from;        }        return a;    }    int Maxflow(int s, int t, int need)    {        this->s = s;        this->t = t;        int flow = 0;        BFS();        memset(num, 0, sizeof(num));        for(int i = 0; i < n; i++) num[d[i]]++;        int x = s;        memset(cur, 0, sizeof(cur));        while(d[s] < n)        {            if(x == t)            {                flow += Augment();                if(flow >= need) return flow;                x = s;            }            int ok = 0;            for(int i = cur[x]; i < G[x].size(); i++)            {                Edge& e = edges[G[x][i]];                if(e.cap > e.flow && d[x] == d[e.to] + 1)   // Advance                {                    ok = 1;                    p[e.to] = G[x][i];                    cur[x] = i; // 注意                    x = e.to;                    break;                }            }            if(!ok)   // Retreat            {                int m = n-1; // 初值注意                for(int i = 0; i < G[x].size(); i++)                {                    Edge& e = edges[G[x][i]];                    if(e.cap > e.flow) m = min(m, d[e.to]);                }                if(--num[d[x]] == 0) break;                num[d[x] = m+1]++;                cur[x] = 0; // 注意                if(x != s) x = edges[p[x]].from;            }        }        return flow;    }} sol;int row[maxn], col[maxn];int mx[maxn][maxn], mn[maxn][maxn];int  m, n, c;void gao(int r, int q, int v, int flag){    if(r == 0 && q == 0)    {        for(int i = 1; i <= m; i ++)            for(int j = 1; j <= n; j ++)            {                if(flag) mx[i][j] = min(mx[i][j], v);                else mn[i][j] = max(mn[i][j], v);            }    }    else if(r == 0)    {        for(int i = 1; i <= m; i ++)        {            if(flag) mx[i][q] = min(mx[i][q], v);            else mn[i][q] = max(mn[i][q], v);        }    }    else if(c == 0)    {        for(int i = 1; i <= n; i ++)        {            if(flag) mx[r][i] = min(mx[r][i], v);            else mn[r][i] = max(mn[r][i], v);        }    }    else    {        if(flag) mx[r][q] = min(mx[r][q], v);        else mn[r][q] = max(mn[r][q], v);    }}bool check(int l, int r){    for(int i = l; i < r; i += 2)    {        Edge e = sol.edges[i];        if(e.flow < e.cap) return false;    }    for(int i = 1; i <= m; i ++)        for(int j = 1; j <= n; j ++)            if(mn[i][j] > mx[i][j]) return false;    return true;}void work(){    scanf("%d%d", &m, &n);    int sumc = 0, sumr = 0;    for(int i = 1; i <= m; i ++) scanf("%d", &row[i]), sumr += row[i];    for(int i = 1; i <= n; i ++) scanf("%d", &col[i]), sumc += col[i];    CLR(mn, 0); CLR(mx, INF);    scanf("%d", &c);    for(int i = 0; i < c; i ++)    {        int r, q, v; char op[4];        scanf("%d%d%s%d", &r, &q, op, &v);        if(op[0] == '=')        {            gao(r, q, v, 1);            gao(r, q, v, 0);        }        else if(op[0] == '<')            gao(r, q, v - 1, 1);        else            gao(r, q, v + 1, 0);    }    sol.init(n + m + 5);    int s = 0, t = n + m + 1, ss = m + n + 2, st = n + m + 3;    for(int i = 1; i <= m; i ++)        for(int j = 1; j <= n; j ++)        {            sol.AddEdge(i, m + j, mx[i][j] - mn[i][j]);        }    for(int i = 1; i <= m; i ++)    {        sol.AddEdge(ss, i, row[i]);        int sum = 0;        for(int j = 1; j <= n; j ++)            sum += mn[i][j];        sol.AddEdge(i, st, sum);    }    for(int i = 1; i <= n; i ++)    {        sol.AddEdge(i + m, st, col[i]);        int sum = 0;        for(int j = 1; j <= m; j ++)            sum += mn[j][i];        sol.AddEdge(ss, i + m, sum);    }    sol.AddEdge(s, st, sumr);    sol.AddEdge(ss, t, sumc);    for(int i = 1; i <= m; i ++)        sol.AddEdge(s, i, 0);    for(int i = 1; i <= n; i ++)        sol.AddEdge(i + m, t, 0);    sol.AddEdge(t, s, INF);    sol.Maxflow(ss, st, INF);    if(check(n*m*2, n*m*2+4*n+4*m+4))    {        for(int i = 0; i < m*n*2; i += 2)        {            int r = i/(n*2) + 1, c = i%(n*2)/2 + 1;            printf("%d", sol.edges[i].flow + mn[r][c]);            if(i % (n * 2) == n*2 - 2) puts("");            else printf(" ");        }    }    else puts("IMPOSSIBLE");}int main(){    int T, flag = false;    scanf("%d", &T);    while(T --)    {        if(flag) puts("");        flag = true;        work();    }}


1 0